From e11f298d0fd2f270d5f2b6a147b8deccbe66bf80 Mon Sep 17 00:00:00 2001 From: salander85 Date: Mon, 9 Oct 2023 12:00:39 +0200 Subject: [PATCH 01/14] Migrate SyncerFactory --- .../project/sync/SyncerFactory.java | 57 ++++++++++--------- 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/src/main/java/com/commercetools/project/sync/SyncerFactory.java b/src/main/java/com/commercetools/project/sync/SyncerFactory.java index 6057e267..7610d27d 100644 --- a/src/main/java/com/commercetools/project/sync/SyncerFactory.java +++ b/src/main/java/com/commercetools/project/sync/SyncerFactory.java @@ -4,10 +4,15 @@ import static com.commercetools.project.sync.CliRunner.SYNC_MODULE_OPTION_DESCRIPTION; import static com.commercetools.project.sync.CliRunner.SYNC_MODULE_OPTION_LONG; import static com.commercetools.project.sync.CliRunner.SYNC_MODULE_OPTION_SHORT; -import static io.sphere.sdk.utils.CompletableFutureUtils.exceptionallyCompletedFuture; +import static io.vrap.rmf.base.client.utils.CompletableFutureUtils.exceptionallyCompletedFuture; import static java.lang.String.format; import static org.apache.commons.lang3.StringUtils.isBlank; +import com.commercetools.api.client.ProjectApiRoot; +import com.commercetools.api.models.PagedQueryResourceRequest; +import com.commercetools.api.models.ResourcePagedQueryResponse; +import com.commercetools.api.models.ResourceUpdateAction; +import com.commercetools.api.models.common.BaseResource; import com.commercetools.project.sync.cartdiscount.CartDiscountSyncer; import com.commercetools.project.sync.category.CategorySyncer; import com.commercetools.project.sync.customer.CustomerSyncer; @@ -24,10 +29,6 @@ import com.commercetools.sync.commons.BaseSync; import com.commercetools.sync.commons.BaseSyncOptions; import com.commercetools.sync.commons.helpers.BaseSyncStatistics; -import io.sphere.sdk.client.SphereClient; -import io.sphere.sdk.models.ResourceView; -import io.sphere.sdk.models.Versioned; -import io.sphere.sdk.queries.QueryDsl; import java.time.Clock; import java.util.ArrayList; import java.util.Arrays; @@ -43,14 +44,14 @@ import javax.annotation.Nullable; public final class SyncerFactory { - private final Supplier targetClientSupplier; - private final Supplier sourceClientSupplier; + private final Supplier targetClientSupplier; + private final Supplier sourceClientSupplier; private final Clock clock; private final boolean shouldCloseClients; private SyncerFactory( - @Nonnull final Supplier sourceClient, - @Nonnull final Supplier targetClient, + @Nonnull final Supplier sourceClient, + @Nonnull final Supplier targetClient, @Nonnull final Clock clock, final boolean closeClients) { this.targetClientSupplier = targetClient; @@ -61,16 +62,16 @@ private SyncerFactory( @Nonnull public static SyncerFactory of( - @Nonnull final Supplier sourceClient, - @Nonnull final Supplier targetClient, + @Nonnull final Supplier sourceClient, + @Nonnull final Supplier targetClient, @Nonnull final Clock clock) { return new SyncerFactory(sourceClient, targetClient, clock, true); } @Nonnull public static SyncerFactory of( - @Nonnull final Supplier sourceClient, - @Nonnull final Supplier targetClient, + @Nonnull final Supplier sourceClient, + @Nonnull final Supplier targetClient, @Nonnull final Clock clock, final boolean closeClients) { return new SyncerFactory(sourceClient, targetClient, clock, closeClients); @@ -127,14 +128,14 @@ private CompletableFuture chainSyncExecution( for (SyncModuleOption syncOptionValue : syncOptions) { Syncer< - ? extends ResourceView, - ? extends ResourceView, + ? extends BaseResource, + ? extends ResourceUpdateAction, ?, - ? extends Versioned, ? extends BaseSyncStatistics, ? extends BaseSyncOptions, - ? extends QueryDsl, - ? extends BaseSync> + ? extends PagedQueryResourceRequest, + ? extends ResourcePagedQueryResponse, + ? extends BaseSync> syncer = buildSyncer( syncOptionValue, @@ -286,14 +287,14 @@ private void closeClients() { * @return The instance of the syncer corresponding to the passed option value. */ private Syncer< - ? extends ResourceView, - ? extends ResourceView, + ? extends BaseResource, + ? extends ResourceUpdateAction, ?, - ? extends Versioned, ? extends BaseSyncStatistics, ? extends BaseSyncOptions, - ? extends QueryDsl, - ? extends BaseSync> + ? extends PagedQueryResourceRequest, + ? extends ResourcePagedQueryResponse, + ? extends BaseSync> buildSyncer( @Nonnull final SyncModuleOption syncModuleOption, @Nonnull final String runnerNameOptionValue, @@ -301,14 +302,14 @@ private void closeClients() { @Nullable final ProductSyncCustomRequest productSyncCustomRequest) { Syncer< - ? extends ResourceView, - ? extends ResourceView, + ? extends BaseResource, + ? extends ResourceUpdateAction, ?, - ? extends Versioned, ? extends BaseSyncStatistics, ? extends BaseSyncOptions, - ? extends QueryDsl, - ? extends BaseSync> + ? extends PagedQueryResourceRequest, + ? extends ResourcePagedQueryResponse, + ? extends BaseSync> syncer = null; switch (syncModuleOption) { From 25fc48d8474c2f5a616ca8a592f7015248e60a28 Mon Sep 17 00:00:00 2001 From: salander85 Date: Mon, 9 Oct 2023 12:01:04 +0200 Subject: [PATCH 02/14] Migrate client utils and rename --- ...CategorySyncWithReferenceResolutionIT.java | 4 +- .../project/sync/CliRunnerIT.java | 4 +- .../sync/InventorySyncMultiChannelIT.java | 4 +- .../sync/ProductSyncWithDiscountedPrice.java | 4 +- .../ProductSyncWithMasterVariantSwitchIT.java | 4 +- .../ProductSyncWithNestedReferencesIT.java | 4 +- .../ProductSyncWithReferenceResolutionIT.java | 4 +- .../sync/ProductSyncWithReferencesIT.java | 4 +- .../sync/util/IntegrationTestUtils.java | 4 +- .../project/sync/SyncerApplication.java | 4 +- .../project/sync/util/CtpClientUtils.java | 156 ++++++++++++++++++ .../project/sync/util/SphereClientUtils.java | 52 ------ .../ctp.credentials.properties.skeleton | 2 +- 13 files changed, 177 insertions(+), 73 deletions(-) create mode 100644 src/main/java/com/commercetools/project/sync/util/CtpClientUtils.java delete mode 100644 src/main/java/com/commercetools/project/sync/util/SphereClientUtils.java diff --git a/src/integration-test/java/com/commercetools/project/sync/CategorySyncWithReferenceResolutionIT.java b/src/integration-test/java/com/commercetools/project/sync/CategorySyncWithReferenceResolutionIT.java index fdab1105..c6aa072b 100644 --- a/src/integration-test/java/com/commercetools/project/sync/CategorySyncWithReferenceResolutionIT.java +++ b/src/integration-test/java/com/commercetools/project/sync/CategorySyncWithReferenceResolutionIT.java @@ -1,10 +1,10 @@ package com.commercetools.project.sync; +import static com.commercetools.project.sync.util.CtpClientUtils.CTP_SOURCE_CLIENT; +import static com.commercetools.project.sync.util.CtpClientUtils.CTP_TARGET_CLIENT; import static com.commercetools.project.sync.util.IntegrationTestUtils.assertCategoryExists; import static com.commercetools.project.sync.util.IntegrationTestUtils.cleanUpProjects; import static com.commercetools.project.sync.util.IntegrationTestUtils.createITSyncerFactory; -import static com.commercetools.project.sync.util.SphereClientUtils.CTP_SOURCE_CLIENT; -import static com.commercetools.project.sync.util.SphereClientUtils.CTP_TARGET_CLIENT; import static io.sphere.sdk.models.LocalizedString.ofEnglish; import static java.util.Arrays.asList; import static java.util.Collections.emptyList; diff --git a/src/integration-test/java/com/commercetools/project/sync/CliRunnerIT.java b/src/integration-test/java/com/commercetools/project/sync/CliRunnerIT.java index 2ed2f8b7..cf2ef8a4 100644 --- a/src/integration-test/java/com/commercetools/project/sync/CliRunnerIT.java +++ b/src/integration-test/java/com/commercetools/project/sync/CliRunnerIT.java @@ -1,14 +1,14 @@ package com.commercetools.project.sync; import static com.commercetools.project.sync.service.impl.CustomObjectServiceImpl.TIMESTAMP_GENERATOR_KEY; +import static com.commercetools.project.sync.util.CtpClientUtils.CTP_SOURCE_CLIENT; +import static com.commercetools.project.sync.util.CtpClientUtils.CTP_TARGET_CLIENT; import static com.commercetools.project.sync.util.IntegrationTestUtils.assertCategoryExists; import static com.commercetools.project.sync.util.IntegrationTestUtils.assertProductExists; import static com.commercetools.project.sync.util.IntegrationTestUtils.assertProductTypeExists; import static com.commercetools.project.sync.util.IntegrationTestUtils.cleanUpProjects; import static com.commercetools.project.sync.util.IntegrationTestUtils.createITSyncerFactory; import static com.commercetools.project.sync.util.QueryUtils.queryAndExecute; -import static com.commercetools.project.sync.util.SphereClientUtils.CTP_SOURCE_CLIENT; -import static com.commercetools.project.sync.util.SphereClientUtils.CTP_TARGET_CLIENT; import static com.commercetools.project.sync.util.SyncUtils.APPLICATION_DEFAULT_NAME; import static com.commercetools.project.sync.util.SyncUtils.DEFAULT_RUNNER_NAME; import static com.commercetools.project.sync.util.TestUtils.assertCartDiscountSyncerLoggingEvents; diff --git a/src/integration-test/java/com/commercetools/project/sync/InventorySyncMultiChannelIT.java b/src/integration-test/java/com/commercetools/project/sync/InventorySyncMultiChannelIT.java index eaa1ea8c..5ab9d2c7 100644 --- a/src/integration-test/java/com/commercetools/project/sync/InventorySyncMultiChannelIT.java +++ b/src/integration-test/java/com/commercetools/project/sync/InventorySyncMultiChannelIT.java @@ -1,9 +1,9 @@ package com.commercetools.project.sync; +import static com.commercetools.project.sync.util.CtpClientUtils.CTP_SOURCE_CLIENT; +import static com.commercetools.project.sync.util.CtpClientUtils.CTP_TARGET_CLIENT; import static com.commercetools.project.sync.util.IntegrationTestUtils.cleanUpProjects; import static com.commercetools.project.sync.util.IntegrationTestUtils.createITSyncerFactory; -import static com.commercetools.project.sync.util.SphereClientUtils.CTP_SOURCE_CLIENT; -import static com.commercetools.project.sync.util.SphereClientUtils.CTP_TARGET_CLIENT; import static java.util.Collections.singletonList; import static org.assertj.core.api.Assertions.assertThat; diff --git a/src/integration-test/java/com/commercetools/project/sync/ProductSyncWithDiscountedPrice.java b/src/integration-test/java/com/commercetools/project/sync/ProductSyncWithDiscountedPrice.java index 85516e6b..bfae1407 100644 --- a/src/integration-test/java/com/commercetools/project/sync/ProductSyncWithDiscountedPrice.java +++ b/src/integration-test/java/com/commercetools/project/sync/ProductSyncWithDiscountedPrice.java @@ -1,9 +1,9 @@ package com.commercetools.project.sync; +import static com.commercetools.project.sync.util.CtpClientUtils.CTP_SOURCE_CLIENT; +import static com.commercetools.project.sync.util.CtpClientUtils.CTP_TARGET_CLIENT; import static com.commercetools.project.sync.util.IntegrationTestUtils.cleanUpProjects; import static com.commercetools.project.sync.util.IntegrationTestUtils.createITSyncerFactory; -import static com.commercetools.project.sync.util.SphereClientUtils.CTP_SOURCE_CLIENT; -import static com.commercetools.project.sync.util.SphereClientUtils.CTP_TARGET_CLIENT; import static com.neovisionaries.i18n.CountryCode.DE; import static io.sphere.sdk.models.DefaultCurrencyUnits.EUR; import static io.sphere.sdk.models.LocalizedString.ofEnglish; diff --git a/src/integration-test/java/com/commercetools/project/sync/ProductSyncWithMasterVariantSwitchIT.java b/src/integration-test/java/com/commercetools/project/sync/ProductSyncWithMasterVariantSwitchIT.java index 7b3e2308..6fed98fb 100644 --- a/src/integration-test/java/com/commercetools/project/sync/ProductSyncWithMasterVariantSwitchIT.java +++ b/src/integration-test/java/com/commercetools/project/sync/ProductSyncWithMasterVariantSwitchIT.java @@ -1,9 +1,9 @@ package com.commercetools.project.sync; +import static com.commercetools.project.sync.util.CtpClientUtils.CTP_SOURCE_CLIENT; +import static com.commercetools.project.sync.util.CtpClientUtils.CTP_TARGET_CLIENT; import static com.commercetools.project.sync.util.IntegrationTestUtils.cleanUpProjects; import static com.commercetools.project.sync.util.IntegrationTestUtils.createITSyncerFactory; -import static com.commercetools.project.sync.util.SphereClientUtils.CTP_SOURCE_CLIENT; -import static com.commercetools.project.sync.util.SphereClientUtils.CTP_TARGET_CLIENT; import static io.sphere.sdk.models.LocalizedString.ofEnglish; import static org.assertj.core.api.Assertions.assertThat; diff --git a/src/integration-test/java/com/commercetools/project/sync/ProductSyncWithNestedReferencesIT.java b/src/integration-test/java/com/commercetools/project/sync/ProductSyncWithNestedReferencesIT.java index 86bc1666..62c626a9 100644 --- a/src/integration-test/java/com/commercetools/project/sync/ProductSyncWithNestedReferencesIT.java +++ b/src/integration-test/java/com/commercetools/project/sync/ProductSyncWithNestedReferencesIT.java @@ -1,5 +1,7 @@ package com.commercetools.project.sync; +import static com.commercetools.project.sync.util.CtpClientUtils.CTP_SOURCE_CLIENT; +import static com.commercetools.project.sync.util.CtpClientUtils.CTP_TARGET_CLIENT; import static com.commercetools.project.sync.util.IntegrationTestUtils.assertCategoryExists; import static com.commercetools.project.sync.util.IntegrationTestUtils.assertCustomerExists; import static com.commercetools.project.sync.util.IntegrationTestUtils.assertProductTypeExists; @@ -8,8 +10,6 @@ import static com.commercetools.project.sync.util.IntegrationTestUtils.createAttributeObject; import static com.commercetools.project.sync.util.IntegrationTestUtils.createITSyncerFactory; import static com.commercetools.project.sync.util.IntegrationTestUtils.createReferenceObject; -import static com.commercetools.project.sync.util.SphereClientUtils.CTP_SOURCE_CLIENT; -import static com.commercetools.project.sync.util.SphereClientUtils.CTP_TARGET_CLIENT; import static com.commercetools.project.sync.util.TestUtils.assertCartDiscountSyncerLoggingEvents; import static com.commercetools.project.sync.util.TestUtils.assertCategorySyncerLoggingEvents; import static com.commercetools.project.sync.util.TestUtils.assertCustomObjectSyncerLoggingEvents; diff --git a/src/integration-test/java/com/commercetools/project/sync/ProductSyncWithReferenceResolutionIT.java b/src/integration-test/java/com/commercetools/project/sync/ProductSyncWithReferenceResolutionIT.java index 5766fbc6..cf03f1ac 100644 --- a/src/integration-test/java/com/commercetools/project/sync/ProductSyncWithReferenceResolutionIT.java +++ b/src/integration-test/java/com/commercetools/project/sync/ProductSyncWithReferenceResolutionIT.java @@ -1,12 +1,12 @@ package com.commercetools.project.sync; +import static com.commercetools.project.sync.util.CtpClientUtils.CTP_SOURCE_CLIENT; +import static com.commercetools.project.sync.util.CtpClientUtils.CTP_TARGET_CLIENT; import static com.commercetools.project.sync.util.IntegrationTestUtils.assertCategoryExists; import static com.commercetools.project.sync.util.IntegrationTestUtils.assertProductExists; import static com.commercetools.project.sync.util.IntegrationTestUtils.assertProductTypeExists; import static com.commercetools.project.sync.util.IntegrationTestUtils.cleanUpProjects; import static com.commercetools.project.sync.util.IntegrationTestUtils.createITSyncerFactory; -import static com.commercetools.project.sync.util.SphereClientUtils.CTP_SOURCE_CLIENT; -import static com.commercetools.project.sync.util.SphereClientUtils.CTP_TARGET_CLIENT; import static com.neovisionaries.i18n.CountryCode.DE; import static io.sphere.sdk.models.DefaultCurrencyUnits.EUR; import static io.sphere.sdk.models.LocalizedString.ofEnglish; diff --git a/src/integration-test/java/com/commercetools/project/sync/ProductSyncWithReferencesIT.java b/src/integration-test/java/com/commercetools/project/sync/ProductSyncWithReferencesIT.java index 08015ba4..87d33306 100644 --- a/src/integration-test/java/com/commercetools/project/sync/ProductSyncWithReferencesIT.java +++ b/src/integration-test/java/com/commercetools/project/sync/ProductSyncWithReferencesIT.java @@ -1,11 +1,11 @@ package com.commercetools.project.sync; +import static com.commercetools.project.sync.util.CtpClientUtils.CTP_SOURCE_CLIENT; +import static com.commercetools.project.sync.util.CtpClientUtils.CTP_TARGET_CLIENT; import static com.commercetools.project.sync.util.IntegrationTestUtils.assertProductTypeExists; import static com.commercetools.project.sync.util.IntegrationTestUtils.cleanUpProjects; import static com.commercetools.project.sync.util.IntegrationTestUtils.createITSyncerFactory; import static com.commercetools.project.sync.util.IntegrationTestUtils.createReferenceObject; -import static com.commercetools.project.sync.util.SphereClientUtils.CTP_SOURCE_CLIENT; -import static com.commercetools.project.sync.util.SphereClientUtils.CTP_TARGET_CLIENT; import static com.commercetools.project.sync.util.TestUtils.assertCartDiscountSyncerLoggingEvents; import static com.commercetools.project.sync.util.TestUtils.assertCategorySyncerLoggingEvents; import static com.commercetools.project.sync.util.TestUtils.assertCustomObjectSyncerLoggingEvents; diff --git a/src/integration-test/java/com/commercetools/project/sync/util/IntegrationTestUtils.java b/src/integration-test/java/com/commercetools/project/sync/util/IntegrationTestUtils.java index c24cab53..5dbbcf5e 100644 --- a/src/integration-test/java/com/commercetools/project/sync/util/IntegrationTestUtils.java +++ b/src/integration-test/java/com/commercetools/project/sync/util/IntegrationTestUtils.java @@ -1,9 +1,9 @@ package com.commercetools.project.sync.util; import static com.commercetools.project.sync.service.impl.CustomObjectServiceImpl.TIMESTAMP_GENERATOR_KEY; +import static com.commercetools.project.sync.util.CtpClientUtils.CTP_SOURCE_CLIENT; +import static com.commercetools.project.sync.util.CtpClientUtils.CTP_TARGET_CLIENT; import static com.commercetools.project.sync.util.QueryUtils.queryAndExecute; -import static com.commercetools.project.sync.util.SphereClientUtils.CTP_SOURCE_CLIENT; -import static com.commercetools.project.sync.util.SphereClientUtils.CTP_TARGET_CLIENT; import static java.lang.String.format; import static org.assertj.core.api.Assertions.assertThat; diff --git a/src/main/java/com/commercetools/project/sync/SyncerApplication.java b/src/main/java/com/commercetools/project/sync/SyncerApplication.java index 40284fa5..a424cd3d 100644 --- a/src/main/java/com/commercetools/project/sync/SyncerApplication.java +++ b/src/main/java/com/commercetools/project/sync/SyncerApplication.java @@ -1,7 +1,7 @@ package com.commercetools.project.sync; -import static com.commercetools.project.sync.util.SphereClientUtils.CTP_SOURCE_CLIENT; -import static com.commercetools.project.sync.util.SphereClientUtils.CTP_TARGET_CLIENT; +import static com.commercetools.project.sync.util.CtpClientUtils.CTP_SOURCE_CLIENT; +import static com.commercetools.project.sync.util.CtpClientUtils.CTP_TARGET_CLIENT; import java.time.Clock; diff --git a/src/main/java/com/commercetools/project/sync/util/CtpClientUtils.java b/src/main/java/com/commercetools/project/sync/util/CtpClientUtils.java new file mode 100644 index 00000000..d304e6c9 --- /dev/null +++ b/src/main/java/com/commercetools/project/sync/util/CtpClientUtils.java @@ -0,0 +1,156 @@ +package com.commercetools.project.sync.util; + +import static java.lang.String.format; + +import com.commercetools.api.client.ProjectApiRoot; +import com.commercetools.api.defaultconfig.ServiceRegion; +import com.commercetools.sync.commons.utils.ClientConfigurationUtils; +import io.vrap.rmf.base.client.oauth2.ClientCredentials; +import java.io.InputStream; +import java.util.InvalidPropertiesFormatException; +import java.util.Properties; +import javax.annotation.Nonnull; + +public final class CtpClientUtils { + private static final String CTP_CREDENTIALS_PROPERTIES = "ctp.credentials.properties"; + public static final String PROPERTIES_KEY_API_URL_SUFFIX = "apiUrl"; + public static final String PROPERTIES_KEY_AUTH_URL_SUFFIX = "authUrl"; + public static final String PROPERTIES_KEY_PROJECT_KEY_SUFFIX = "projectKey"; + public static final String PROPERTIES_KEY_CLIENT_ID_SUFFIX = "clientId"; + public static final String PROPERTIES_KEY_CLIENT_SECRET_SUFFIX = "clientSecret"; + public static final String PROPERTIES_KEY_SCOPES_SUFFIX = "scopes"; + + public static final ProjectApiRoot CTP_SOURCE_CLIENT = getCtpSourceClient(); + public static final ProjectApiRoot CTP_TARGET_CLIENT = getCtpTargetClient(); + + private static ProjectApiRoot getCtpSourceClient() { + return getCtpClient("source."); + } + + private static ProjectApiRoot getCtpTargetClient() { + return getCtpClient("target."); + } + + private static ProjectApiRoot getCtpClient(@Nonnull final String propertiesPrefix) { + try { + InputStream propStream = + CtpClientUtils.class.getClassLoader().getResourceAsStream(CTP_CREDENTIALS_PROPERTIES); + Properties properties = new Properties(); + if (propStream != null) { + properties.load(propStream); + } + if (properties.isEmpty()) { + properties = loadFromEnvVars(propertiesPrefix); + } + if (properties.isEmpty()) { + throw new InvalidPropertiesFormatException("Please provide CTP credentials for running project sync."); + } + + final String projectKey = + extract(properties, propertiesPrefix, PROPERTIES_KEY_PROJECT_KEY_SUFFIX); + final String clientId = + extract(properties, propertiesPrefix, PROPERTIES_KEY_CLIENT_ID_SUFFIX); + final String clientSecret = + extract(properties, propertiesPrefix, PROPERTIES_KEY_CLIENT_SECRET_SUFFIX); + final String apiUrl = + extract( + properties, + propertiesPrefix, + PROPERTIES_KEY_API_URL_SUFFIX, + ServiceRegion.GCP_EUROPE_WEST1.getApiUrl()); + + final String authUrl = + extract( + properties, + propertiesPrefix, + PROPERTIES_KEY_AUTH_URL_SUFFIX, + ServiceRegion.GCP_EUROPE_WEST1.getOAuthTokenUrl()); + final String scopes = + extract( + properties, + propertiesPrefix, + PROPERTIES_KEY_SCOPES_SUFFIX, + "manage_project:" + projectKey); + + final ClientCredentials credentials = + ClientCredentials.of() + .withClientId(clientId) + .withClientSecret(clientSecret) + .withScopes(scopes) + .build(); + + return ClientConfigurationUtils.createClient(projectKey, credentials, authUrl, apiUrl); + } catch (Exception exception) { + throw new IllegalStateException( + format( + "IT properties file \"%s\" found, but CTP properties" + + " for prefix \"%s\" can't be read", + CTP_CREDENTIALS_PROPERTIES, propertiesPrefix), + exception); + } + } + + private static Properties loadFromEnvVars(String propertiesPrefix) { + String projectKeyKey = propertiesPrefix.toUpperCase().replace(".", "_") + "PROJECT_KEY"; + String projectKey = System.getenv(projectKeyKey); + String clientIdKey = propertiesPrefix.toUpperCase().replace(".", "_") + "CLIENT_ID"; + String clientId = System.getenv(clientIdKey); + String clientSecretKey = propertiesPrefix.toUpperCase().replace(".", "_") + "CLIENT_SECRET"; + String clientSecret = System.getenv(clientSecretKey); + Properties properties = new Properties(); + properties.put(propertiesPrefix + PROPERTIES_KEY_PROJECT_KEY_SUFFIX, projectKey); + properties.put(propertiesPrefix + PROPERTIES_KEY_CLIENT_ID_SUFFIX, clientId); + properties.put(propertiesPrefix + PROPERTIES_KEY_CLIENT_SECRET_SUFFIX, clientSecret); + return properties; + } + + private static String extract( + final Properties properties, + final String prefix, + final String suffix, + final String defaultValue) { + return properties.getProperty(buildPropKey(prefix, suffix), defaultValue); + } + + private static String extract( + final Properties properties, final String prefix, final String suffix) { + final String mapKey = buildPropKey(prefix, suffix); + return properties + .computeIfAbsent(mapKey, key -> throwPropertiesException(prefix, mapKey)) + .toString(); + } + + private static String buildPropKey(final String prefix, final String suffix) { + return prefix + suffix; + } + + private static String throwPropertiesException(final String prefix, final String missingKey) { + throw new IllegalArgumentException( + "Missing property value '" + + missingKey + + "'.\n" + + "Usage:\n" + + "" + + buildPropKey(prefix, PROPERTIES_KEY_PROJECT_KEY_SUFFIX) + + "=YOUR project key\n" + + "" + + buildPropKey(prefix, PROPERTIES_KEY_CLIENT_ID_SUFFIX) + + "=YOUR client id\n" + + "" + + buildPropKey(prefix, PROPERTIES_KEY_CLIENT_SECRET_SUFFIX) + + "=YOUR client secret\n" + + "#optional:\n" + + "" + + buildPropKey(prefix, PROPERTIES_KEY_API_URL_SUFFIX) + + "=https://api.europe-west1.gcp.commercetools.com\n" + + "" + + buildPropKey(prefix, PROPERTIES_KEY_AUTH_URL_SUFFIX) + + "=https://auth.europe-west1.gcp.commercetools.com\n" + + "" + + buildPropKey(prefix, PROPERTIES_KEY_SCOPES_SUFFIX) + + "=manage_project" + + "#don't use quotes for the property values\n"); + } + + private CtpClientUtils() {} +} diff --git a/src/main/java/com/commercetools/project/sync/util/SphereClientUtils.java b/src/main/java/com/commercetools/project/sync/util/SphereClientUtils.java deleted file mode 100644 index 220d8284..00000000 --- a/src/main/java/com/commercetools/project/sync/util/SphereClientUtils.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.commercetools.project.sync.util; - -import static java.lang.String.format; - -import com.commercetools.sync.commons.utils.ClientConfigurationUtils; -import io.sphere.sdk.client.SphereClient; -import io.sphere.sdk.client.SphereClientConfig; -import java.io.InputStream; -import java.util.Properties; -import javax.annotation.Nonnull; - -public final class SphereClientUtils { - private static final String CTP_CREDENTIALS_PROPERTIES = "ctp.credentials.properties"; - public static final SphereClientConfig CTP_SOURCE_CLIENT_CONFIG = getCtpSourceClientConfig(); - public static final SphereClientConfig CTP_TARGET_CLIENT_CONFIG = getCtpTargetClientConfig(); - public static final SphereClient CTP_SOURCE_CLIENT = - ClientConfigurationUtils.createClient(CTP_SOURCE_CLIENT_CONFIG); - public static final SphereClient CTP_TARGET_CLIENT = - ClientConfigurationUtils.createClient(CTP_TARGET_CLIENT_CONFIG); - - private static SphereClientConfig getCtpSourceClientConfig() { - return getCtpClientConfig("source.", "SOURCE"); - } - - private static SphereClientConfig getCtpTargetClientConfig() { - return getCtpClientConfig("target.", "TARGET"); - } - - private static SphereClientConfig getCtpClientConfig( - @Nonnull final String propertiesPrefix, @Nonnull final String envVarPrefix) { - try { - final InputStream propStream = - SphereClientUtils.class.getClassLoader().getResourceAsStream(CTP_CREDENTIALS_PROPERTIES); - if (propStream != null) { - final Properties ctpCredsProperties = new Properties(); - ctpCredsProperties.load(propStream); - return SphereClientConfig.ofProperties(ctpCredsProperties, propertiesPrefix); - } - } catch (Exception exception) { - throw new IllegalStateException( - format( - "CTP credentials file \"%s\" found, but CTP properties" - + " for prefix \"%s\" can't be read", - CTP_CREDENTIALS_PROPERTIES, propertiesPrefix), - exception); - } - - return SphereClientConfig.ofEnvironmentVariables(envVarPrefix); - } - - private SphereClientUtils() {} -} diff --git a/src/main/resources/ctp.credentials.properties.skeleton b/src/main/resources/ctp.credentials.properties.skeleton index 5f9dbdc9..6e426f69 100644 --- a/src/main/resources/ctp.credentials.properties.skeleton +++ b/src/main/resources/ctp.credentials.properties.skeleton @@ -1,5 +1,5 @@ # rename to ctp.credentials.properties and fill the values to run the job locally without env variables -# see SphereClientUtils for more info +# see CtpClientUtils for more info source.projectKey=<> source.clientId=YOUR client id without quotes source.clientSecret=YOUR client secret without quotes From ae84cbce1e2b25c87a3632a3baea35e982b61085 Mon Sep 17 00:00:00 2001 From: salander85 Date: Mon, 9 Oct 2023 12:48:55 +0200 Subject: [PATCH 03/14] Migrate CliRunner --- src/main/java/com/commercetools/project/sync/CliRunner.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/commercetools/project/sync/CliRunner.java b/src/main/java/com/commercetools/project/sync/CliRunner.java index 14406af8..f5cb9aa0 100644 --- a/src/main/java/com/commercetools/project/sync/CliRunner.java +++ b/src/main/java/com/commercetools/project/sync/CliRunner.java @@ -3,7 +3,7 @@ import static com.commercetools.project.sync.model.ProductSyncCustomRequest.parseProductQueryParametersOption; import static com.commercetools.project.sync.util.SyncUtils.getApplicationName; import static com.commercetools.project.sync.util.SyncUtils.getApplicationVersion; -import static io.sphere.sdk.utils.CompletableFutureUtils.exceptionallyCompletedFuture; +import static io.vrap.rmf.base.client.utils.CompletableFutureUtils.exceptionallyCompletedFuture; import static java.lang.String.format; import com.commercetools.project.sync.exception.CliException; From 90b08162e5fd046b23f4fe206d25f8cdb6db2add Mon Sep 17 00:00:00 2001 From: salander85 Date: Tue, 17 Oct 2023 16:22:43 +0200 Subject: [PATCH 04/14] Migrate unittests for SyncerFactory --- .../project/sync/SyncerFactoryTest.java | 2642 +++++++++-------- .../project/sync/util/TestUtils.java | 55 +- 2 files changed, 1455 insertions(+), 1242 deletions(-) diff --git a/src/test/java/com/commercetools/project/sync/SyncerFactoryTest.java b/src/test/java/com/commercetools/project/sync/SyncerFactoryTest.java index 046d1214..8a9e1e3b 100644 --- a/src/test/java/com/commercetools/project/sync/SyncerFactoryTest.java +++ b/src/test/java/com/commercetools/project/sync/SyncerFactoryTest.java @@ -1,9 +1,60 @@ package com.commercetools.project.sync; +import static com.commercetools.project.sync.CliRunner.SYNC_MODULE_OPTION_DESCRIPTION; +import static com.commercetools.project.sync.service.impl.CustomObjectServiceImpl.TIMESTAMP_GENERATOR_KEY; +import static com.commercetools.project.sync.util.SyncUtils.DEFAULT_RUNNER_NAME; +import static com.commercetools.project.sync.util.SyncUtils.getApplicationName; +import static com.commercetools.project.sync.util.TestUtils.assertCartDiscountSyncerLoggingEvents; +import static com.commercetools.project.sync.util.TestUtils.assertCategorySyncerLoggingEvents; +import static com.commercetools.project.sync.util.TestUtils.assertCustomObjectSyncerLoggingEvents; +import static com.commercetools.project.sync.util.TestUtils.assertCustomerSyncerLoggingEvents; +import static com.commercetools.project.sync.util.TestUtils.assertInventoryEntrySyncerLoggingEvents; +import static com.commercetools.project.sync.util.TestUtils.assertProductSyncerLoggingEvents; +import static com.commercetools.project.sync.util.TestUtils.assertProductTypeSyncerLoggingEvents; +import static com.commercetools.project.sync.util.TestUtils.assertShoppingListSyncerLoggingEvents; +import static com.commercetools.project.sync.util.TestUtils.assertStateSyncerLoggingEvents; +import static com.commercetools.project.sync.util.TestUtils.assertTaxCategorySyncerLoggingEvents; +import static com.commercetools.project.sync.util.TestUtils.assertTypeSyncerLoggingEvents; +import static com.commercetools.project.sync.util.TestUtils.createBadGatewayException; +import static com.commercetools.project.sync.util.TestUtils.getMockedClock; +import static com.commercetools.project.sync.util.TestUtils.mockLastSyncCustomObject; +import static com.commercetools.project.sync.util.TestUtils.readObjectFromResource; +import static com.commercetools.project.sync.util.TestUtils.readStringFromFile; +import static com.commercetools.project.sync.util.TestUtils.stubClientsCustomObjectService; +import static com.commercetools.project.sync.util.TestUtils.withTestClient; +import static java.lang.String.format; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.atLeast; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; +import static org.mockito.Mockito.when; + +import com.commercetools.api.client.ByProjectKeyCustomObjectsPost; +import com.commercetools.api.client.ByProjectKeyProductsPost; +import com.commercetools.api.client.ProjectApiRoot; +import com.commercetools.api.defaultconfig.ApiRootBuilder; +import com.commercetools.api.models.ResourcePagedQueryResponse; +import com.commercetools.api.models.custom_object.CustomObject; +import com.commercetools.api.models.custom_object.CustomObjectDraft; +import com.commercetools.api.models.graph_ql.GraphQLRequest; +import com.commercetools.api.models.graph_ql.GraphQLRequestBuilder; +import com.commercetools.api.models.product.Product; +import com.commercetools.api.models.product.ProductDraft; +import com.commercetools.api.models.product.ProductMixin; +import com.commercetools.api.models.product.ProductProjection; +import com.commercetools.api.models.product.ProductProjectionPagedQueryResponse; +import com.commercetools.api.models.product.ProductProjectionPagedQueryResponseBuilder; +import com.commercetools.api.models.product.ProductProjectionType; import com.commercetools.project.sync.cartdiscount.CartDiscountSyncer; import com.commercetools.project.sync.category.CategorySyncer; import com.commercetools.project.sync.customer.CustomerSyncer; import com.commercetools.project.sync.customobject.CustomObjectSyncer; +import com.commercetools.project.sync.exception.CliException; import com.commercetools.project.sync.inventoryentry.InventoryEntrySyncer; import com.commercetools.project.sync.product.ProductSyncer; import com.commercetools.project.sync.producttype.ProductTypeSyncer; @@ -11,15 +62,41 @@ import com.commercetools.project.sync.state.StateSyncer; import com.commercetools.project.sync.taxcategory.TaxCategorySyncer; import com.commercetools.project.sync.type.TypeSyncer; +import com.commercetools.sync.commons.exceptions.ReferenceTransformException; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.vrap.rmf.base.client.ApiHttpMethod; +import io.vrap.rmf.base.client.ApiHttpResponse; +import io.vrap.rmf.base.client.error.BadGatewayException; +import io.vrap.rmf.base.client.utils.CompletableFutureUtils; +import io.vrap.rmf.base.client.utils.json.JsonUtils; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.time.ZonedDateTime; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionStage; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import javax.annotation.Nonnull; +import org.assertj.core.api.Condition; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.InOrder; +import org.mockito.Mockito; +import uk.org.lidalia.slf4jext.Level; +import uk.org.lidalia.slf4jtest.LoggingEvent; import uk.org.lidalia.slf4jtest.TestLogger; import uk.org.lidalia.slf4jtest.TestLoggerFactory; // This will suppress MoreThanOneLogger warnings in this class @SuppressWarnings("PMD.MoreThanOneLogger") - -// These tests aren't migrated -// TODO: Migrate tests class SyncerFactoryTest { private static final TestLogger productSyncerTestLogger = TestLoggerFactory.getTestLogger(ProductSyncer.class); @@ -46,7 +123,41 @@ class SyncerFactoryTest { private static final TestLogger taxCategorySyncerTestLogger = TestLoggerFactory.getTestLogger(TaxCategorySyncer.class); + private ProjectApiRoot sourceClient; + private ProjectApiRoot targetClient; + + private AtomicInteger verifyProductTypesGetCounter, + verifyTypesGetCounter, + verifyStatesGetCounter, + verifyTaxCategoriesGetCounter, + verifyCategoriesGetCounter, + verifyInventoryGetCounter, + verifyProductProjectionsGetCounter, + verifyCartDiscountsGetCounter, + verifyCustomersGetCounter, + verifyCustomObjectsGetCounter, + verifyShoppingListsGetCounter, + verifyInvokeClientCounter; + @BeforeEach + void setupTest() { + verifyProductTypesGetCounter = new AtomicInteger(0); + verifyTypesGetCounter = new AtomicInteger(0); + verifyStatesGetCounter = new AtomicInteger(0); + verifyTaxCategoriesGetCounter = new AtomicInteger(0); + verifyCategoriesGetCounter = new AtomicInteger(0); + verifyInventoryGetCounter = new AtomicInteger(0); + verifyProductProjectionsGetCounter = new AtomicInteger(0); + verifyCustomObjectsGetCounter = new AtomicInteger(0); + verifyCustomersGetCounter = new AtomicInteger(0); + verifyCartDiscountsGetCounter = new AtomicInteger(0); + verifyShoppingListsGetCounter = new AtomicInteger(0); + verifyInvokeClientCounter = new AtomicInteger(0); + sourceClient = mockClientResourceRequests("testProjectKey"); + targetClient = mock(ProjectApiRoot.class); + } + + @AfterEach void tearDownTest() { cliRunnerTestLogger.clearAll(); productSyncerTestLogger.clearAll(); @@ -62,1242 +173,1291 @@ void tearDownTest() { taxCategorySyncerTestLogger.clearAll(); } - // @Test - // void sync_WithNullOptionValue_ShouldCompleteExceptionallyWithIllegalArgumentException() { - // assertThat( - // SyncerFactory.of( - // () -> mock(SphereClient.class), - // () -> mock(SphereClient.class), - // getMockedClock()) - // .sync(new String[] {null}, "myRunnerName", false, false, null)) - // .failsWithin(1, TimeUnit.SECONDS) - // .withThrowableOfType(ExecutionException.class) - // .withCauseExactlyInstanceOf(CliException.class) - // .withMessageContaining( - // format( - // "Blank argument supplied to \"-s\" or \"--sync\" option! %s", - // SYNC_MODULE_OPTION_DESCRIPTION)); - // } - // - // @Test - // void sync_WithEmptyOptionValue_ShouldCompleteExceptionallyWithIllegalArgumentException() { - // assertThat( - // SyncerFactory.of( - // () -> mock(SphereClient.class), - // () -> mock(SphereClient.class), - // getMockedClock()) - // .sync(new String[] {""}, "myRunnerName", false, false, null)) - // .failsWithin(1, TimeUnit.SECONDS) - // .withThrowableOfType(ExecutionException.class) - // .withCauseExactlyInstanceOf(CliException.class) - // .withMessageContaining( - // format( - // "Blank argument supplied to \"-s\" or \"--sync\" option! %s", - // SYNC_MODULE_OPTION_DESCRIPTION)); - // } - // - // @Test - // void sync_WithUnknownOptionValue_ShouldCompleteExceptionallyWithIllegalArgumentException() { - // final String[] unknownOptionValue = {"anyOption"}; - // - // assertThat( - // SyncerFactory.of( - // () -> mock(SphereClient.class), - // () -> mock(SphereClient.class), - // getMockedClock()) - // .sync(unknownOptionValue, "myRunnerName", false, false, null)) - // .failsWithin(1, TimeUnit.SECONDS) - // .withThrowableOfType(ExecutionException.class) - // .withCauseExactlyInstanceOf(CliException.class) - // .withMessageContaining( - // format( - // "Unknown argument \"%s\" supplied to \"-s\" or \"--sync\" option! %s", - // unknownOptionValue[0], SYNC_MODULE_OPTION_DESCRIPTION)); - // } - // - // @Test - // @SuppressWarnings("unchecked") - // void sync_AsProductsDeltaSync_ShouldBuildSyncerAndExecuteSync() { - // // preparation - // final SphereClient sourceClient = mock(SphereClient.class); - // when(sourceClient.getConfig()).thenReturn(SphereClientConfig.of("foo", "foo", "foo")); - // - // final SphereClient targetClient = mock(SphereClient.class); - // when(targetClient.getConfig()).thenReturn(SphereClientConfig.of("bar", "bar", "bar")); - // - // when(sourceClient.execute(any(ProductProjectionQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // - // final SyncerFactory syncerFactory = - // SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock()); - // - // final ZonedDateTime currentCtpTimestamp = ZonedDateTime.now(); - // stubClientsCustomObjectService(targetClient, currentCtpTimestamp); - // - // // test - // syncerFactory.sync(new String[] {"products"}, "myRunnerName", false, false, null); - // - // // assertions - // verify(sourceClient, times(1)).execute(any(ProductProjectionQuery.class)); - // - // verifyTimestampGeneratorCustomObjectUpsertIsCalled(targetClient, "ProductSync", - // "myRunnerName"); - // verifyLastSyncCustomObjectQuery(targetClient, "productSync", "myRunnerName", "foo", 1); - // // verify two custom object upserts : 1. current ctp timestamp and 2. last sync timestamp - // // creation) - // verify(targetClient, times(2)).execute(any(CustomObjectUpsertCommand.class)); - // // TODO: Assert on actual last sync timestamp creation in detail after Statistics classes in - // // java-sync library - // // TODO: override #equals method: - // // https://github.com/commercetools/commercetools-sync-java/issues/376 - // // TODO: e.g. verifyNewLastSyncCustomObjectCreation(targetClient, - // // currentCtpTimestamp.minusMinutes(2), any(ProductSyncStatistics.class), 0L, "productSync", - // // "foo"); - // verifyInteractionsWithClientAfterSync(sourceClient, 1); - // - // final Condition startLog = - // new Condition<>( - // loggingEvent -> - // Level.INFO.equals(loggingEvent.getLevel()) - // && loggingEvent.getMessage().contains("Starting ProductSync"), - // "start log"); - // - // final Condition statisticsLog = - // new Condition<>( - // loggingEvent -> - // Level.INFO.equals(loggingEvent.getLevel()) - // && loggingEvent - // .getMessage() - // .contains( - // "Summary: 0 product(s) were processed in total (0 created, 0 - // updated, " - // + "0 failed to sync and 0 product(s) with missing - // reference(s))."), - // "statistics log"); - // - // assertThat(productSyncerTestLogger.getAllLoggingEvents()) - // .hasSize(2) - // .haveExactly(1, startLog) - // .haveExactly(1, statisticsLog); - // } - // - // @Test - // @SuppressWarnings("unchecked") - // void sync_AsProductsFullSync_ShouldBuildSyncerAndExecuteSync() { - // // preparation - // final SphereClient sourceClient = mock(SphereClient.class); - // when(sourceClient.getConfig()).thenReturn(SphereClientConfig.of("foo", "foo", "foo")); - // - // final SphereClient targetClient = mock(SphereClient.class); - // when(targetClient.getConfig()).thenReturn(SphereClientConfig.of("bar", "bar", "bar")); - // - // when(sourceClient.execute(any(ProductProjectionQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // - // final SyncerFactory syncerFactory = - // SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock()); - // - // final ZonedDateTime currentCtpTimestamp = ZonedDateTime.now(); - // stubClientsCustomObjectService(targetClient, currentCtpTimestamp); - // - // // test - // syncerFactory.sync(new String[] {"products"}, "myRunnerName", true, false, null); - // - // // assertions - // verify(sourceClient, times(1)).execute(any(ProductProjectionQuery.class)); - // - // verifyTimestampGeneratorCustomObjectUpsertIsNotCalled( - // targetClient, "ProductSync", "myRunnerName"); - // verifyLastSyncCustomObjectQuery(targetClient, "productSync", "myRunnerName", "foo", 0); - // verify(targetClient, times(0)).execute(any(CustomObjectUpsertCommand.class)); - // verifyInteractionsWithClientAfterSync(sourceClient, 1); - // - // final Condition startLog = - // new Condition<>( - // loggingEvent -> - // Level.INFO.equals(loggingEvent.getLevel()) - // && loggingEvent.getMessage().contains("Starting ProductSync"), - // "start log"); - // - // final Condition statisticsLog = - // new Condition<>( - // loggingEvent -> - // Level.INFO.equals(loggingEvent.getLevel()) - // && loggingEvent - // .getMessage() - // .contains( - // "Summary: 0 product(s) were processed in total (0 created, 0 - // updated, " - // + "0 failed to sync and 0 product(s) with missing - // reference(s))."), - // "statistics log"); - // - // assertThat(productSyncerTestLogger.getAllLoggingEvents()) - // .hasSize(2) - // .haveExactly(1, startLog) - // .haveExactly(1, statisticsLog); - // } - // - // @Test - // void - // - // sync_AsProductsFullSyncWithExceptionDuringAttributeReferenceReplacement_ShouldBuildSyncerAndExecuteSync() { - // // preparation - // final SphereClient sourceClient = mock(SphereClient.class); - // when(sourceClient.getConfig()).thenReturn(SphereClientConfig.of("foo", "foo", "foo")); - // - // final SphereClient targetClient = mock(SphereClient.class); - // when(targetClient.getConfig()).thenReturn(SphereClientConfig.of("bar", "bar", "bar")); - // - // final ProductProjection product5 = - // SphereJsonUtils.readObjectFromResource("product-key-5.json", Product.class) - // .toProjection(STAGED); - // final ProductProjection product6 = - // SphereJsonUtils.readObjectFromResource("product-key-6.json", Product.class) - // .toProjection(STAGED); - // final PagedQueryResult twoProductResult = - // MockPagedQueryResult.of(asList(product5, product6)); - // - // when(sourceClient.execute(any(ProductProjectionQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(twoProductResult)); - // - // when(targetClient.execute(any())).thenReturn(CompletableFuture.completedFuture(null)); - // final BadGatewayException badGatewayException = new BadGatewayException("Error!"); - // when(targetClient.execute(any(ProductCreateCommand.class))) - // .thenReturn(CompletableFutureUtils.failed(badGatewayException)); - // when(sourceClient.execute(any(ResourceIdsGraphQlRequest.class))) - // .thenReturn(CompletableFutureUtils.failed(badGatewayException)); - // - // final SyncerFactory syncerFactory = - // SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock()); - // - // // test - // syncerFactory.sync(new String[] {"products"}, "myRunnerName", true, false, null); - // - // // assertions - // verify(sourceClient, times(1)).execute(any(ProductProjectionQuery.class)); - // verify(sourceClient, times(3)).execute(any(ResourceIdsGraphQlRequest.class)); - // verifyInteractionsWithClientAfterSync(sourceClient, 1); - // - // final Condition startLog = - // new Condition<>( - // loggingEvent -> - // Level.INFO.equals(loggingEvent.getLevel()) - // && loggingEvent.getMessage().contains("Starting ProductSync"), - // "start log"); - // - // final Condition statisticsLog = - // new Condition<>( - // loggingEvent -> - // Level.INFO.equals(loggingEvent.getLevel()) - // && loggingEvent - // .getMessage() - // .contains( - // "Summary: 0 product(s) were processed in total (0 created, 0 - // updated, " - // + "0 failed to sync and 0 product(s) with missing - // reference(s))."), - // "statistics log"); - // - // assertThat(productSyncerTestLogger.getAllLoggingEvents()) - // .hasSize(3) - // .haveExactly(1, startLog) - // .haveExactly(1, statisticsLog); - // - // assertThat(productSyncerTestLogger.getAllLoggingEvents()) - // .anySatisfy( - // loggingEvent -> { - // assertThat(loggingEvent.getMessage()) - // .contains( - // ReferenceTransformException.class.getCanonicalName() - // + ": Failed to replace referenced resource ids with keys on the - // attributes of the " - // + "products in the current fetched page from the source project. " - // + "This page will not be synced to the target project."); - // assertThat(loggingEvent.getThrowable().isPresent()).isTrue(); - // assertThat(loggingEvent.getThrowable().get().getCause().getCause()) - // .isEqualTo(badGatewayException); - // }); - // } - // - // @Test - // void - // - // sync_AsProductsFullSyncWithExceptionDuringAttributeReferenceReplacement_ShouldContinueWithPages() { - // // preparation - // final SphereClient sourceClient = mock(SphereClient.class); - // when(sourceClient.getConfig()).thenReturn(SphereClientConfig.of("foo", "foo", "foo")); - // - // final SphereClient targetClient = mock(SphereClient.class); - // when(targetClient.getConfig()).thenReturn(SphereClientConfig.of("bar", "bar", "bar")); - // - // final ProductProjection product1 = - // SphereJsonUtils.readObjectFromResource("product-key-7.json", Product.class) - // .toProjection(STAGED); - // final ProductProjection product2 = - // SphereJsonUtils.readObjectFromResource("product-key-8.json", Product.class) - // .toProjection(STAGED); - // final ProductProjection product3 = - // SphereJsonUtils.readObjectFromResource("product-key-9.json", Product.class) - // .toProjection(STAGED); - // - // final List fullPageOfProducts = - // IntStream.range(0, 500).mapToObj(o -> product1).collect(Collectors.toList()); - // - // when(sourceClient.execute(any(ProductProjectionQuery.class))) - // - // .thenReturn(CompletableFuture.completedFuture(MockPagedQueryResult.of(fullPageOfProducts))) - // .thenReturn( - // CompletableFuture.completedFuture(MockPagedQueryResult.of(asList(product3, - // product2)))); - // - // when(targetClient.execute(any(ProductProjectionQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(MockPagedQueryResult.of(emptyList()))); - // when(targetClient.execute(any(ProductTypeQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(MockPagedQueryResult.of(emptyList()))); - // when(targetClient.execute(any(CategoryQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(MockPagedQueryResult.of(emptyList()))); - // when(targetClient.execute(any(TaxCategoryQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(MockPagedQueryResult.of(emptyList()))); - // when(targetClient.execute(any(StateQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(MockPagedQueryResult.of(emptyList()))); - // when(targetClient.execute(any(CustomObjectQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(MockPagedQueryResult.of(emptyList()))); - // - // final Product product4 = - // SphereJsonUtils.readObjectFromResource("product-key-8.json", Product.class); - // - // when(targetClient.execute(any(ProductCreateCommand.class))) - // .thenReturn(CompletableFuture.completedFuture(product4)); - // - // String jsonAsString = - // - // "{\"results\":[{\"id\":\"53c4a8b4-865f-4b95-b6f2-3e1e70e3d0c1\",\"key\":\"productKey3\"}]}"; - // final ResourceKeyIdGraphQlResult productsResult = - // SphereJsonUtils.readObject(jsonAsString, ResourceKeyIdGraphQlResult.class); - // - // String jsonStringProductTypes = - // - // "{\"results\":[{\"id\":\"53c4a8b4-865f-4b95-b6f2-3e1e70e3d0c2\",\"key\":\"prodType1\"}]}"; - // final ResourceKeyIdGraphQlResult productTypesResult = - // SphereJsonUtils.readObject(jsonStringProductTypes, ResourceKeyIdGraphQlResult.class); - // - // String jsonStringCategories = - // "{\"results\":[{\"id\":\"53c4a8b4-865f-4b95-b6f2-3e1e70e3d0c3\",\"key\":\"cat1\"}]}"; - // final ResourceKeyIdGraphQlResult categoriesResult = - // SphereJsonUtils.readObject(jsonStringCategories, ResourceKeyIdGraphQlResult.class); - // - // final BadGatewayException badGatewayException = new BadGatewayException("Error!"); - // when(sourceClient.execute(any(ResourceIdsGraphQlRequest.class))) - // .thenReturn(CompletableFutureUtils.failed(badGatewayException)) - // .thenReturn(CompletableFutureUtils.failed(badGatewayException)) - // .thenReturn(CompletableFutureUtils.failed(badGatewayException)) - // .thenReturn(CompletableFuture.completedFuture(productsResult)) - // .thenReturn(CompletableFuture.completedFuture(categoriesResult)) - // .thenReturn(CompletableFuture.completedFuture(productTypesResult)); - // - // final ResourceKeyIdGraphQlResult resourceKeyIdGraphQlResult = - // mock(ResourceKeyIdGraphQlResult.class); - // when(resourceKeyIdGraphQlResult.getResults()) - // .thenReturn( - // singleton(new ResourceKeyId("productKey3", - // "53c4a8b4-865f-4b95-b6f2-3e1e70e3d0c1"))); - // when(targetClient.execute(any(ResourceKeyIdGraphQlRequest.class))) - // .thenReturn(CompletableFuture.completedFuture(resourceKeyIdGraphQlResult)); - // - // final SyncerFactory syncerFactory = - // SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock()); - // - // // test - // syncerFactory.sync(new String[] {"products"}, "myRunnerName", true, false, null); - // - // // assertions - // verify(sourceClient, times(2)).execute(any(ProductProjectionQuery.class)); - // verify(sourceClient, times(9)).execute(any(ResourceIdsGraphQlRequest.class)); - // verifyInteractionsWithClientAfterSync(sourceClient, 1); - // - // final Condition startLog = - // new Condition<>( - // loggingEvent -> - // Level.INFO.equals(loggingEvent.getLevel()) - // && loggingEvent.getMessage().contains("Starting ProductSync"), - // "start log"); - // - // final Condition statisticsLog = - // new Condition<>( - // loggingEvent -> - // Level.INFO.equals(loggingEvent.getLevel()) - // && loggingEvent - // .getMessage() - // .contains( - // "Summary: 2 product(s) were processed in total (2 created, 0 - // updated, " - // + "0 failed to sync and 0 product(s) with missing - // reference(s))."), - // "statistics log"); - // - // assertThat(productSyncerTestLogger.getAllLoggingEvents()) - // .hasSize(3) - // .haveExactly(1, startLog) - // .haveExactly(1, statisticsLog); - // - // assertThat(productSyncerTestLogger.getAllLoggingEvents()) - // .anySatisfy( - // loggingEvent -> { - // assertThat(loggingEvent.getMessage()) - // .contains( - // ReferenceTransformException.class.getCanonicalName() - // + ": Failed to replace referenced resource ids with keys on the - // attributes of the " - // + "products in the current fetched page from the source project. " - // + "This page will not be synced to the target project."); - // assertThat(loggingEvent.getThrowable().isPresent()).isTrue(); - // assertThat(loggingEvent.getThrowable().get().getCause().getCause()) - // .isEqualTo(badGatewayException); - // }); - // } - // - // private static void verifyTimestampGeneratorCustomObjectUpsertIsCalled( - // @Nonnull final SphereClient client, - // @Nonnull final String syncMethodName, - // @Nonnull final String syncRunnerName) { - // final CustomObjectDraft customObjectDraft = - // findTimestampGeneratorCustomObjectUpsert(client, syncMethodName, syncRunnerName); - // assertThat(customObjectDraft).isNotNull(); - // assertThat((String) customObjectDraft.getValue()) - // .matches( - // - // "[0-9a-fA-F]{8}\\-[0-9a-fA-F]{4}\\-[0-9a-fA-F]{4}\\-[0-9a-fA-F]{4}\\-[0-9a-fA-F]{12}"); - // } - // - // private static void verifyTimestampGeneratorCustomObjectUpsertIsNotCalled( - // @Nonnull final SphereClient client, - // @Nonnull final String syncMethodName, - // @Nonnull final String syncRunnerName) { - // final CustomObjectDraft customObjectDraft = - // findTimestampGeneratorCustomObjectUpsert(client, syncMethodName, syncRunnerName); - // assertThat(customObjectDraft).isNull(); - // } - // - // private static CustomObjectDraft findTimestampGeneratorCustomObjectUpsert( - // @Nonnull SphereClient client, - // @Nonnull String syncMethodName, - // @Nonnull String syncRunnerName) { - // // fact: SphereRequest is a very broad interface and we actually wanted to capture only - // // CustomObjectUpsertCommand. - // // I tried it but argumentcaptor captures also CustomObjectQueryImpl classes, because we - // call - // // both query and upsert in the mocked SphereClient. - // // This situation throws runtime NPE error later in the method as query doesnt contain a - // draft. - // // I guess generics doesnt work here as type is not know on compile time. - // // That's why we need to filter instanceof CustomObjectUpsertCommand in the streams. - // final ArgumentCaptor sphereClientArgumentCaptor = - // ArgumentCaptor.forClass(CustomObjectUpsertCommand.class); - // - // verify(client, atLeast(0)).execute(sphereClientArgumentCaptor.capture()); - // final List allValues = sphereClientArgumentCaptor.getAllValues(); - // final CustomObjectDraft customObjectDraft = - // allValues.stream() - // .filter(sphereRequest -> sphereRequest instanceof CustomObjectUpsertCommand) - // .map(sphereRequest -> (CustomObjectUpsertCommand) sphereRequest) - // .map(command -> (CustomObjectDraft) command.getDraft()) - // .filter( - // draft -> { - // return draft - // .getContainer() - // .equals( - // format( - // "%s.%s.%s.%s", - // getApplicationName(), - // syncRunnerName, - // syncMethodName, - // TIMESTAMP_GENERATOR_KEY)) - // && draft.getKey().equals(TIMESTAMP_GENERATOR_KEY); - // }) - // .findAny() - // .orElse(null); - // return customObjectDraft; - // } - // - // private static void verifyLastSyncCustomObjectQuery( - // @Nonnull final SphereClient client, - // @Nonnull final String syncModuleName, - // @Nonnull final String syncRunnerName, - // @Nonnull final String sourceProjectKey, - // final int expectedInvocations) { - // - // final QueryPredicate> queryPredicate = - // QueryPredicate.of( - // format( - // "container=\"commercetools-project-sync.%s.%s\" AND key=\"%s\"", - // syncRunnerName, syncModuleName, sourceProjectKey)); - // - // verify(client, times(expectedInvocations)) - // - // .execute(CustomObjectQuery.of(LastSyncCustomObject.class).plusPredicates(queryPredicate)); - // } - // - // @Test - // @SuppressWarnings("unchecked") - // void sync_AsCategoriesDeltaSync_ShouldBuildSyncerAndExecuteSync() { - // // preparation - // final SphereClient sourceClient = mock(SphereClient.class); - // when(sourceClient.getConfig()).thenReturn(SphereClientConfig.of("foo", "foo", "foo")); - // - // final SphereClient targetClient = mock(SphereClient.class); - // when(targetClient.getConfig()).thenReturn(SphereClientConfig.of("bar", "bar", "bar")); - // - // when(sourceClient.execute(any(CategoryQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // - // final SyncerFactory syncerFactory = - // SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock()); - // - // final ZonedDateTime currentCtpTimestamp = ZonedDateTime.now(); - // stubClientsCustomObjectService(targetClient, currentCtpTimestamp); - // - // // test - // syncerFactory.sync(new String[] {"categories"}, null, false, false, null); - // - // // assertions - // verify(sourceClient, times(1)).execute(any(CategoryQuery.class)); - // verifyTimestampGeneratorCustomObjectUpsertIsCalled( - // targetClient, "CategorySync", DEFAULT_RUNNER_NAME); - // verifyLastSyncCustomObjectQuery(targetClient, "categorySync", DEFAULT_RUNNER_NAME, "foo", - // 1); - // // verify two custom object upserts : 1. current ctp timestamp and 2. last sync timestamp - // // creation) - // verify(targetClient, times(2)).execute(any(CustomObjectUpsertCommand.class)); - // // TODO: Assert on actual last sync timestamp creation in detail after Statistics classes in - // // java-sync library - // // TODO: override #equals method: - // // https://github.com/commercetools/commercetools-sync-java/issues/376 - // // TODO: e.g. verifyNewLastSyncCustomObjectCreation(targetClient, - // // currentCtpTimestamp.minusMinutes(2), any(ProductSyncStatistics.class), 0L, "productSync", - // // "foo"); - // verifyInteractionsWithClientAfterSync(sourceClient, 1); - // - // final Condition startLog = - // new Condition<>( - // loggingEvent -> - // Level.INFO.equals(loggingEvent.getLevel()) - // && loggingEvent.getMessage().contains("Starting CategorySync"), - // "start log"); - // - // final Condition statisticsLog = - // new Condition<>( - // loggingEvent -> - // Level.INFO.equals(loggingEvent.getLevel()) - // && loggingEvent - // .getMessage() - // .contains( - // "Summary: 0 categories were processed in total (0 created, 0 - // updated, " - // + "0 failed to sync and 0 categories with a missing parent)."), - // "statistics log"); - // - // assertThat(categorySyncerTestLogger.getAllLoggingEvents()) - // .hasSize(2) - // .haveExactly(1, startLog) - // .haveExactly(1, statisticsLog); - // } - // - // @Test - // @SuppressWarnings("unchecked") - // void sync_AsProductTypesDeltaSync_ShouldBuildSyncerAndExecuteSync() { - // // preparation - // final SphereClient sourceClient = mock(SphereClient.class); - // when(sourceClient.getConfig()).thenReturn(SphereClientConfig.of("foo", "foo", "foo")); - // - // final SphereClient targetClient = mock(SphereClient.class); - // when(targetClient.getConfig()).thenReturn(SphereClientConfig.of("bar", "bar", "bar")); - // - // when(sourceClient.execute(any(ProductTypeQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // - // final SyncerFactory syncerFactory = - // SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock()); - // - // final ZonedDateTime currentCtpTimestamp = ZonedDateTime.now(); - // stubClientsCustomObjectService(targetClient, currentCtpTimestamp); - // - // // test - // syncerFactory.sync(new String[] {"productTypes"}, "", false, false, null); - // - // // assertions - // verify(sourceClient, times(1)).execute(any(ProductTypeQuery.class)); - // verifyTimestampGeneratorCustomObjectUpsertIsCalled( - // targetClient, "ProductTypeSync", DEFAULT_RUNNER_NAME); - // verifyLastSyncCustomObjectQuery(targetClient, "productTypeSync", DEFAULT_RUNNER_NAME, "foo", - // 1); - // // verify two custom object upserts : 1. current ctp timestamp and 2. last sync timestamp - // // creation) - // verify(targetClient, times(2)).execute(any(CustomObjectUpsertCommand.class)); - // // TODO: Assert on actual last sync timestamp creation in detail after Statistics classes in - // // java-sync library - // // TODO: override #equals method: - // // https://github.com/commercetools/commercetools-sync-java/issues/376 - // // TODO: e.g. verifyNewLastSyncCustomObjectCreation(targetClient, - // // currentCtpTimestamp.minusMinutes(2), any(ProductSyncStatistics.class), 0L, "productSync", - // // "foo"); - // verifyInteractionsWithClientAfterSync(sourceClient, 1); - // - // final Condition startLog = - // new Condition<>( - // loggingEvent -> - // Level.INFO.equals(loggingEvent.getLevel()) - // && loggingEvent.getMessage().contains("Starting ProductTypeSync"), - // "start log"); - // - // final Condition statisticsLog = - // new Condition<>( - // loggingEvent -> - // Level.INFO.equals(loggingEvent.getLevel()) - // && loggingEvent - // .getMessage() - // .contains( - // "Summary: 0 product types were processed in total (0 created, 0 - // updated, 0 failed to sync" - // + " and 0 product types with at least one NestedType or a Set of - // NestedType attribute" - // + " definition(s) referencing a missing product type)."), - // "statistics log"); - // - // assertThat(productTypeSyncerTestLogger.getAllLoggingEvents()) - // .hasSize(2) - // .haveExactly(1, startLog) - // .haveExactly(1, statisticsLog); - // } - // - // @Test - // @SuppressWarnings("unchecked") - // void sync_AsTypesDeltaSync_ShouldBuildSyncerAndExecuteSync() { - // // preparation - // final SphereClient sourceClient = mock(SphereClient.class); - // when(sourceClient.getConfig()).thenReturn(SphereClientConfig.of("foo", "foo", "foo")); - // - // final SphereClient targetClient = mock(SphereClient.class); - // when(targetClient.getConfig()).thenReturn(SphereClientConfig.of("bar", "bar", "bar")); - // - // when(sourceClient.execute(any(TypeQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // - // final ZonedDateTime currentCtpTimestamp = ZonedDateTime.now(); - // stubClientsCustomObjectService(targetClient, currentCtpTimestamp); - // - // final SyncerFactory syncerFactory = - // SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock()); - // - // // test - // syncerFactory.sync(new String[] {"types"}, "foo", false, false, null); - // - // // assertions - // verify(sourceClient, times(1)).execute(any(TypeQuery.class)); - // verifyTimestampGeneratorCustomObjectUpsertIsCalled(targetClient, "TypeSync", "foo"); - // verifyLastSyncCustomObjectQuery(targetClient, "typeSync", "foo", "foo", 1); - // // verify two custom object upserts : 1. current ctp timestamp and 2. last sync timestamp - // // creation) - // verify(targetClient, times(2)).execute(any(CustomObjectUpsertCommand.class)); - // // TODO: Assert on actual last sync timestamp creation in detail after Statistics classes in - // // java-sync library - // // TODO: override #equals method: - // // https://github.com/commercetools/commercetools-sync-java/issues/376 - // // TODO: e.g. verifyNewLastSyncCustomObjectCreation(targetClient, - // // currentCtpTimestamp.minusMinutes(2), any(ProductSyncStatistics.class), 0L, "productSync", - // // "foo"); - // verifyInteractionsWithClientAfterSync(sourceClient, 1); - // - // final Condition startLog = - // new Condition<>( - // loggingEvent -> - // Level.INFO.equals(loggingEvent.getLevel()) - // && loggingEvent.getMessage().contains("Starting TypeSync"), - // "start log"); - // - // final Condition statisticsLog = - // new Condition<>( - // loggingEvent -> - // Level.INFO.equals(loggingEvent.getLevel()) - // && loggingEvent - // .getMessage() - // .contains( - // "Summary: 0 types were processed in total (0 created, 0 updated " - // + "and 0 failed to sync)."), - // "statistics log"); - // - // assertThat(typeSyncerTestLogger.getAllLoggingEvents()) - // .hasSize(2) - // .haveExactly(1, startLog) - // .haveExactly(1, statisticsLog); - // } - // - // @Test - // @SuppressWarnings("unchecked") - // void sync_AsInventoryEntriesDeltaSync_ShouldBuildSyncerAndExecuteSync() { - // // preparation - // final SphereClient sourceClient = mock(SphereClient.class); - // when(sourceClient.getConfig()).thenReturn(SphereClientConfig.of("foo", "foo", "foo")); - // - // final SphereClient targetClient = mock(SphereClient.class); - // when(targetClient.getConfig()).thenReturn(SphereClientConfig.of("bar", "bar", "bar")); - // - // when(sourceClient.execute(any(InventoryEntryQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // - // final ZonedDateTime currentCtpTimestamp = ZonedDateTime.now(); - // stubClientsCustomObjectService(targetClient, currentCtpTimestamp); - // - // final SyncerFactory syncerFactory = - // SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock()); - // - // // test - // syncerFactory.sync(new String[] {"inventoryEntries"}, null, false, false, null); - // - // // assertions - // verify(sourceClient, times(1)).execute(any(InventoryEntryQuery.class)); - // verifyTimestampGeneratorCustomObjectUpsertIsCalled( - // targetClient, "InventorySync", DEFAULT_RUNNER_NAME); - // verifyLastSyncCustomObjectQuery(targetClient, "inventorySync", DEFAULT_RUNNER_NAME, "foo", - // 1); - // // verify two custom object upserts : 1. current ctp timestamp and 2. last sync timestamp - // // creation) - // verify(targetClient, times(2)).execute(any(CustomObjectUpsertCommand.class)); - // // TODO: Assert on actual last sync timestamp creation in detail after Statistics classes in - // // java-sync library - // // TODO: override #equals method: - // // https://github.com/commercetools/commercetools-sync-java/issues/376 - // // TODO: e.g. verifyNewLastSyncCustomObjectCreation(targetClient, - // // currentCtpTimestamp.minusMinutes(2), any(ProductSyncStatistics.class), 0L, "productSync", - // // "foo"); - // verifyInteractionsWithClientAfterSync(sourceClient, 1); - // - // final Condition startLog = - // new Condition<>( - // loggingEvent -> - // Level.INFO.equals(loggingEvent.getLevel()) - // && loggingEvent.getMessage().contains("Starting InventorySync"), - // "start log"); - // - // final Condition statisticsLog = - // new Condition<>( - // loggingEvent -> - // Level.INFO.equals(loggingEvent.getLevel()) - // && loggingEvent - // .getMessage() - // .contains( - // "Summary: 0 inventory entries were processed in total (0 created, 0 - // updated " - // + "and 0 failed to sync)."), - // "statistics log"); - // - // assertThat(inventoryEntrySyncerTestLogger.getAllLoggingEvents()) - // .hasSize(2) - // .haveExactly(1, startLog) - // .haveExactly(1, statisticsLog); - // } - // - // @Test - // void sync_WithErrorOnFetch_ShouldCloseClientAndCompleteExceptionally() { - // // preparation - // final SphereClient sourceClient = mock(SphereClient.class); - // when(sourceClient.getConfig()).thenReturn(SphereClientConfig.of("foo", "foo", "foo")); - // - // final SphereClient targetClient = mock(SphereClient.class); - // when(targetClient.getConfig()).thenReturn(SphereClientConfig.of("bar", "bar", "bar")); - // - // final BadGatewayException badGatewayException = new BadGatewayException(); - // when(sourceClient.execute(any(InventoryEntryQuery.class))) - // .thenReturn(CompletableFutureUtils.exceptionallyCompletedFuture(badGatewayException)); - // - // final ZonedDateTime currentCtpTimestamp = ZonedDateTime.now(); - // stubClientsCustomObjectService(targetClient, currentCtpTimestamp); - // - // final SyncerFactory syncerFactory = - // SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock()); - // - // // test - // final CompletionStage result = - // syncerFactory.sync(new String[] {"inventoryEntries"}, null, false, false, null); - // - // // assertions - // verifyTimestampGeneratorCustomObjectUpsertIsCalled( - // targetClient, "InventorySync", DEFAULT_RUNNER_NAME); - // verify(sourceClient, times(1)).execute(any(InventoryEntryQuery.class)); - // verifyInteractionsWithClientAfterSync(sourceClient, 1); - // assertThat(result) - // .failsWithin(1, TimeUnit.SECONDS) - // .withThrowableOfType(ExecutionException.class) - // .withCauseExactlyInstanceOf(BadGatewayException.class); - // } - // - // @Test - // @SuppressWarnings("unchecked") - // void - // - // sync_WithErrorOnCurrentCtpTimestampUpsert_ShouldCloseClientAndCompleteExceptionallyWithoutSyncing() { - // // preparation - // final SphereClient sourceClient = mock(SphereClient.class); - // when(sourceClient.getConfig()).thenReturn(SphereClientConfig.of("foo", "foo", "foo")); - // - // final SphereClient targetClient = mock(SphereClient.class); - // when(targetClient.getConfig()).thenReturn(SphereClientConfig.of("bar", "bar", "bar")); - // - // final BadGatewayException badGatewayException = new BadGatewayException(); - // when(targetClient.execute(any(CustomObjectUpsertCommand.class))) - // .thenReturn(CompletableFutureUtils.exceptionallyCompletedFuture(badGatewayException)); - // - // final SyncerFactory syncerFactory = - // SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock()); - // - // // test - // final CompletionStage result = - // syncerFactory.sync(new String[] {"inventoryEntries"}, "", false, false, null); - // - // // assertions - // verifyTimestampGeneratorCustomObjectUpsertIsCalled( - // targetClient, "InventorySync", DEFAULT_RUNNER_NAME); - // verify(sourceClient, times(0)).execute(any(InventoryEntryQuery.class)); - // verifyInteractionsWithClientAfterSync(sourceClient, 1); - // assertThat(result) - // .failsWithin(1, TimeUnit.SECONDS) - // .withThrowableOfType(ExecutionException.class) - // .withCauseExactlyInstanceOf(BadGatewayException.class); - // } - // - // @Test - // @SuppressWarnings("unchecked") - // void - // - // sync_WithErrorOnQueryLastSyncTimestamp_ShouldCloseClientAndCompleteExceptionallyWithoutSyncing() { - // // preparation - // final SphereClient sourceClient = mock(SphereClient.class); - // when(sourceClient.getConfig()).thenReturn(SphereClientConfig.of("foo", "foo", "foo")); - // - // final SphereClient targetClient = mock(SphereClient.class); - // when(targetClient.getConfig()).thenReturn(SphereClientConfig.of("bar", "bar", "bar")); - // - // final BadGatewayException badGatewayException = new BadGatewayException(); - // when(targetClient.execute(any(CustomObjectQuery.class))) - // .thenReturn(CompletableFutureUtils.exceptionallyCompletedFuture(badGatewayException)); - // - // final CustomObject> - // lastSyncCustomObjectCustomObject = mockLastSyncCustomObject(ZonedDateTime.now()); - // when(targetClient.execute(any(CustomObjectUpsertCommand.class))) - // .thenReturn(CompletableFuture.completedFuture(lastSyncCustomObjectCustomObject)); - // - // final SyncerFactory syncerFactory = - // SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock()); - // - // // test - // final CompletionStage result = - // syncerFactory.sync(new String[] {"inventoryEntries"}, "bar", false, false, null); - // - // // assertions - // verifyTimestampGeneratorCustomObjectUpsertIsCalled(targetClient, "InventorySync", "bar"); - // verifyLastSyncCustomObjectQuery(targetClient, "inventorySync", "bar", "foo", 1); - // verify(sourceClient, times(0)).execute(any(InventoryEntryQuery.class)); - // verifyInteractionsWithClientAfterSync(sourceClient, 1); - // assertThat(result) - // .failsWithin(1, TimeUnit.SECONDS) - // .withThrowableOfType(ExecutionException.class) - // .withCauseExactlyInstanceOf(BadGatewayException.class); - // } - // - // @Test - // @SuppressWarnings("unchecked") - // void syncAll_AsDelta_ShouldBuildSyncerAndExecuteSync() { - // // preparation - // final SphereClient sourceClient = mock(SphereClient.class); - // when(sourceClient.getConfig()).thenReturn(SphereClientConfig.of("foo", "foo", "foo")); - // - // final SphereClient targetClient = mock(SphereClient.class); - // when(targetClient.getConfig()).thenReturn(SphereClientConfig.of("bar", "bar", "bar")); - // - // when(sourceClient.execute(any(ProductTypeQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // when(sourceClient.execute(any(TypeQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // when(sourceClient.execute(any(StateQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // when(sourceClient.execute(any(TaxCategoryQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // when(sourceClient.execute(any(CategoryQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // when(sourceClient.execute(any(InventoryEntryQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // when(sourceClient.execute(any(ProductProjectionQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // when(sourceClient.execute(any(CartDiscountQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // when(sourceClient.execute(any(CustomObjectQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // when(sourceClient.execute(any(CustomerQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // when(sourceClient.execute(any(ShoppingListQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // - // final ZonedDateTime currentCtpTimestamp = ZonedDateTime.now(); - // stubClientsCustomObjectService(targetClient, currentCtpTimestamp); - // - // final SyncerFactory syncerFactory = - // SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock()); - // - // // test - // syncerFactory.sync(new String[] {"all"}, null, false, false, null).join(); - // - // // assertions - // verifyTimestampGeneratorCustomObjectUpsertIsCalled( - // targetClient, "ProductTypeSync", DEFAULT_RUNNER_NAME); - // verifyTimestampGeneratorCustomObjectUpsertIsCalled( - // targetClient, "ProductSync", DEFAULT_RUNNER_NAME); - // verifyTimestampGeneratorCustomObjectUpsertIsCalled( - // targetClient, "CategorySync", DEFAULT_RUNNER_NAME); - // verifyTimestampGeneratorCustomObjectUpsertIsCalled( - // targetClient, "TypeSync", DEFAULT_RUNNER_NAME); - // verifyTimestampGeneratorCustomObjectUpsertIsCalled( - // targetClient, "InventorySync", DEFAULT_RUNNER_NAME); - // verifyTimestampGeneratorCustomObjectUpsertIsCalled( - // targetClient, "CartDiscountSync", DEFAULT_RUNNER_NAME); - // verifyTimestampGeneratorCustomObjectUpsertIsCalled( - // targetClient, "StateSync", DEFAULT_RUNNER_NAME); - // verifyTimestampGeneratorCustomObjectUpsertIsCalled( - // targetClient, "TaxCategorySync", DEFAULT_RUNNER_NAME); - // verifyTimestampGeneratorCustomObjectUpsertIsCalled( - // targetClient, "CustomObjectSync", DEFAULT_RUNNER_NAME); - // verifyTimestampGeneratorCustomObjectUpsertIsCalled( - // targetClient, "CustomerSync", DEFAULT_RUNNER_NAME); - // verifyTimestampGeneratorCustomObjectUpsertIsCalled( - // targetClient, "ShoppingListSync", DEFAULT_RUNNER_NAME); - // verify(targetClient, times(22)).execute(any(CustomObjectUpsertCommand.class)); - // verifyLastSyncCustomObjectQuery(targetClient, "inventorySync", DEFAULT_RUNNER_NAME, "foo", - // 1); - // verifyLastSyncCustomObjectQuery(targetClient, "productTypeSync", DEFAULT_RUNNER_NAME, "foo", - // 1); - // verifyLastSyncCustomObjectQuery(targetClient, "productSync", DEFAULT_RUNNER_NAME, "foo", 1); - // verifyLastSyncCustomObjectQuery(targetClient, "categorySync", DEFAULT_RUNNER_NAME, "foo", - // 1); - // verifyLastSyncCustomObjectQuery(targetClient, "typeSync", DEFAULT_RUNNER_NAME, "foo", 1); - // verifyLastSyncCustomObjectQuery( - // targetClient, "cartDiscountSync", DEFAULT_RUNNER_NAME, "foo", 1); - // verifyLastSyncCustomObjectQuery(targetClient, "stateSync", DEFAULT_RUNNER_NAME, "foo", 1); - // verifyLastSyncCustomObjectQuery(targetClient, "taxCategorySync", DEFAULT_RUNNER_NAME, "foo", - // 1); - // verifyLastSyncCustomObjectQuery( - // targetClient, "customObjectSync", DEFAULT_RUNNER_NAME, "foo", 1); - // verifyLastSyncCustomObjectQuery(targetClient, "customerSync", DEFAULT_RUNNER_NAME, "foo", - // 1); - // verifyLastSyncCustomObjectQuery( - // targetClient, "shoppingListSync", DEFAULT_RUNNER_NAME, "foo", 1); - // verify(sourceClient, times(1)).execute(any(ProductTypeQuery.class)); - // verify(sourceClient, times(1)).execute(any(TypeQuery.class)); - // verify(sourceClient, times(1)).execute(any(CategoryQuery.class)); - // verify(sourceClient, times(1)).execute(any(ProductProjectionQuery.class)); - // verify(sourceClient, times(1)).execute(any(InventoryEntryQuery.class)); - // verify(sourceClient, times(1)).execute(any(CartDiscountQuery.class)); - // verify(sourceClient, times(1)).execute(any(StateQuery.class)); - // verify(sourceClient, times(1)).execute(any(TaxCategoryQuery.class)); - // verify(sourceClient, times(1)).execute(any(CustomObjectQuery.class)); - // verify(sourceClient, times(1)).execute(any(CustomerQuery.class)); - // verify(sourceClient, times(1)).execute(any(ShoppingListQuery.class)); - // verifyInteractionsWithClientAfterSync(sourceClient, 11); - // - // assertThat(cliRunnerTestLogger.getAllLoggingEvents()) - // .allMatch(loggingEvent -> !Level.ERROR.equals(loggingEvent.getLevel())); - // - // assertThat(productSyncerTestLogger.getAllLoggingEvents()) - // .allMatch(loggingEvent -> !Level.ERROR.equals(loggingEvent.getLevel())); - // - // assertTypeSyncerLoggingEvents(typeSyncerTestLogger, 0); - // assertProductTypeSyncerLoggingEvents(productTypeSyncerTestLogger, 0); - // assertCategorySyncerLoggingEvents(categorySyncerTestLogger, 0); - // assertProductSyncerLoggingEvents(productSyncerTestLogger, 0); - // assertInventoryEntrySyncerLoggingEvents(inventoryEntrySyncerTestLogger, 0); - // assertCartDiscountSyncerLoggingEvents(cartDiscountSyncerTestLogger, 0); - // // +1 state is a built-in state and it cant be deleted - // assertStateSyncerLoggingEvents(stateSyncerTestLogger, 0); - // assertTaxCategorySyncerLoggingEvents(taxCategorySyncerTestLogger, 0); - // assertCustomObjectSyncerLoggingEvents(customObjectSyncerTestLogger, 0); - // assertCustomerSyncerLoggingEvents(customerSyncerTestLogger, 0); - // assertShoppingListSyncerLoggingEvents(shoppingListSyncerTestLogger, 0); - // - // // Every sync module is expected to have 2 logs (start and stats summary) - // assertThat(typeSyncerTestLogger.getAllLoggingEvents()).hasSize(2); - // assertThat(productTypeSyncerTestLogger.getAllLoggingEvents()).hasSize(2); - // assertThat(categorySyncerTestLogger.getAllLoggingEvents()).hasSize(2); - // assertThat(productSyncerTestLogger.getAllLoggingEvents()).hasSize(2); - // assertThat(inventoryEntrySyncerTestLogger.getAllLoggingEvents()).hasSize(2); - // assertThat(cartDiscountSyncerTestLogger.getAllLoggingEvents()).hasSize(2); - // assertThat(stateSyncerTestLogger.getAllLoggingEvents()).hasSize(2); - // assertThat(taxCategorySyncerTestLogger.getAllLoggingEvents()).hasSize(2); - // assertThat(customObjectSyncerTestLogger.getAllLoggingEvents()).hasSize(2); - // assertThat(customerSyncerTestLogger.getAllLoggingEvents()).hasSize(2); - // assertThat(shoppingListSyncerTestLogger.getAllLoggingEvents()).hasSize(2); - // } - // - // @Test - // @SuppressWarnings("unchecked") - // void - // syncProductTypesProductsCustomersAndShoppingLists_AsDelta_ShouldBuildSyncerAndExecuteSync() { - // // preparation - // final SphereClient sourceClient = mock(SphereClient.class); - // when(sourceClient.getConfig()).thenReturn(SphereClientConfig.of("foo", "foo", "foo")); - // - // final SphereClient targetClient = mock(SphereClient.class); - // when(targetClient.getConfig()).thenReturn(SphereClientConfig.of("bar", "bar", "bar")); - // - // when(sourceClient.execute(any(ProductTypeQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // when(sourceClient.execute(any(ProductProjectionQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // when(sourceClient.execute(any(CustomerQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // when(sourceClient.execute(any(ShoppingListQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // - // final ZonedDateTime currentCtpTimestamp = ZonedDateTime.now(); - // stubClientsCustomObjectService(targetClient, currentCtpTimestamp); - // - // final SyncerFactory syncerFactory = - // SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock()); - // - // // test - // String[] syncModuleOptions = {"productTypes", "products", "customers", "shoppingLists"}; - // syncerFactory.sync(syncModuleOptions, null, false, false, null).join(); - // - // // assertions - // verifyTimestampGeneratorCustomObjectUpsertIsCalled( - // targetClient, "ProductTypeSync", DEFAULT_RUNNER_NAME); - // verifyTimestampGeneratorCustomObjectUpsertIsCalled( - // targetClient, "ProductSync", DEFAULT_RUNNER_NAME); - // verifyTimestampGeneratorCustomObjectUpsertIsCalled( - // targetClient, "CustomerSync", DEFAULT_RUNNER_NAME); - // verifyTimestampGeneratorCustomObjectUpsertIsCalled( - // targetClient, "ShoppingListSync", DEFAULT_RUNNER_NAME); - // verify(targetClient, times(8)).execute(any(CustomObjectUpsertCommand.class)); - // verifyLastSyncCustomObjectQuery(targetClient, "productTypeSync", DEFAULT_RUNNER_NAME, "foo", - // 1); - // verifyLastSyncCustomObjectQuery(targetClient, "productSync", DEFAULT_RUNNER_NAME, "foo", 1); - // verifyLastSyncCustomObjectQuery(targetClient, "customerSync", DEFAULT_RUNNER_NAME, "foo", - // 1); - // verifyLastSyncCustomObjectQuery( - // targetClient, "shoppingListSync", DEFAULT_RUNNER_NAME, "foo", 1); - // - // final InOrder inOrder = Mockito.inOrder(sourceClient); - // - // // According to sync algorithm, ProductType and Customer will run sync in parallel, Product - // and - // // ShoppingList sequentially. - // // Example: Given: ['productTypes', 'customers', 'products', 'shoppingLists'] - // // From the given arguments, algorithm will group the resources as below, - // // [productTypes, customers] [products] [shoppingLists] - // inOrder.verify(sourceClient, times(1)).execute(any(ProductTypeQuery.class)); - // verify(sourceClient, times(1)).execute(any(CustomerQuery.class)); - // - // inOrder.verify(sourceClient, times(1)).execute(any(ProductProjectionQuery.class)); - // - // inOrder.verify(sourceClient, times(1)).execute(any(ShoppingListQuery.class)); - // verifyInteractionsWithClientAfterSync(sourceClient, 4); - // - // assertProductTypeSyncerLoggingEvents(productTypeSyncerTestLogger, 0); - // assertProductSyncerLoggingEvents(productSyncerTestLogger, 0); - // assertCustomerSyncerLoggingEvents(customerSyncerTestLogger, 0); - // assertShoppingListSyncerLoggingEvents(shoppingListSyncerTestLogger, 0); - // } - // - // @Test - // @SuppressWarnings("unchecked") - // void syncStatesInventoryEntriesAndCustomObjects_AsDelta_ShouldBuildSyncerAndExecuteSync() { - // // preparation - // final SphereClient sourceClient = mock(SphereClient.class); - // when(sourceClient.getConfig()).thenReturn(SphereClientConfig.of("foo", "foo", "foo")); - // - // final SphereClient targetClient = mock(SphereClient.class); - // when(targetClient.getConfig()).thenReturn(SphereClientConfig.of("bar", "bar", "bar")); - // - // when(sourceClient.execute(any(StateQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // when(sourceClient.execute(any(InventoryEntryQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // when(sourceClient.execute(any(CustomObjectQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // - // final ZonedDateTime currentCtpTimestamp = ZonedDateTime.now(); - // stubClientsCustomObjectService(targetClient, currentCtpTimestamp); - // - // final SyncerFactory syncerFactory = - // SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock()); - // - // // test - // String[] syncModuleOptions = {"states", "inventoryEntries", "customObjects"}; - // syncerFactory.sync(syncModuleOptions, null, false, false, null).join(); - // - // // assertions - // verifyTimestampGeneratorCustomObjectUpsertIsCalled( - // targetClient, "StateSync", DEFAULT_RUNNER_NAME); - // verifyTimestampGeneratorCustomObjectUpsertIsCalled( - // targetClient, "InventorySync", DEFAULT_RUNNER_NAME); - // verifyTimestampGeneratorCustomObjectUpsertIsCalled( - // targetClient, "CustomObjectSync", DEFAULT_RUNNER_NAME); - // verify(targetClient, times(6)).execute(any(CustomObjectUpsertCommand.class)); - // verifyLastSyncCustomObjectQuery(targetClient, "stateSync", DEFAULT_RUNNER_NAME, "foo", 1); - // verifyLastSyncCustomObjectQuery(targetClient, "inventorySync", DEFAULT_RUNNER_NAME, "foo", - // 1); - // verifyLastSyncCustomObjectQuery( - // targetClient, "customObjectSync", DEFAULT_RUNNER_NAME, "foo", 1); - // verify(sourceClient, times(1)).execute(any(StateQuery.class)); - // verify(sourceClient, times(1)).execute(any(InventoryEntryQuery.class)); - // verify(sourceClient, times(1)).execute(any(CustomObjectQuery.class)); - // verifyInteractionsWithClientAfterSync(sourceClient, 3); - // - // assertStateSyncerLoggingEvents(stateSyncerTestLogger, 0); - // assertInventoryEntrySyncerLoggingEvents(inventoryEntrySyncerTestLogger, 0); - // assertCustomObjectSyncerLoggingEvents(customObjectSyncerTestLogger, 0); - // } - // - // @Test - // @SuppressWarnings("unchecked") - // void syncTypesAndCategories_AsDelta_ShouldBuildSyncerAndExecuteSync() { - // // preparation - // final SphereClient sourceClient = mock(SphereClient.class); - // when(sourceClient.getConfig()).thenReturn(SphereClientConfig.of("foo", "foo", "foo")); - // - // final SphereClient targetClient = mock(SphereClient.class); - // when(targetClient.getConfig()).thenReturn(SphereClientConfig.of("bar", "bar", "bar")); - // - // when(sourceClient.execute(any(TypeQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // when(sourceClient.execute(any(CategoryQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // - // final ZonedDateTime currentCtpTimestamp = ZonedDateTime.now(); - // stubClientsCustomObjectService(targetClient, currentCtpTimestamp); - // - // final SyncerFactory syncerFactory = - // SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock()); - // - // // test - // String[] syncModuleOptions = {"types", "categories"}; - // syncerFactory.sync(syncModuleOptions, null, false, false, null).join(); - // - // // assertions - // verifyTimestampGeneratorCustomObjectUpsertIsCalled( - // targetClient, "TypeSync", DEFAULT_RUNNER_NAME); - // verifyTimestampGeneratorCustomObjectUpsertIsCalled( - // targetClient, "CategorySync", DEFAULT_RUNNER_NAME); - // verify(targetClient, times(4)).execute(any(CustomObjectUpsertCommand.class)); - // verifyLastSyncCustomObjectQuery(targetClient, "typeSync", DEFAULT_RUNNER_NAME, "foo", 1); - // verifyLastSyncCustomObjectQuery(targetClient, "categorySync", DEFAULT_RUNNER_NAME, "foo", - // 1); - // - // final InOrder inOrder = Mockito.inOrder(sourceClient); - // - // inOrder.verify(sourceClient, times(1)).execute(any(TypeQuery.class)); - // inOrder.verify(sourceClient, times(1)).execute(any(CategoryQuery.class)); - // verifyInteractionsWithClientAfterSync(sourceClient, 2); - // - // assertTypeSyncerLoggingEvents(typeSyncerTestLogger, 0); - // assertCategorySyncerLoggingEvents(categorySyncerTestLogger, 0); - // assertThat(typeSyncerTestLogger.getAllLoggingEvents()).hasSize(2); - // assertThat(categorySyncerTestLogger.getAllLoggingEvents()).hasSize(2); - // } - // - // @Test - // @SuppressWarnings("unchecked") - // void syncProductsAndShoppingLists_AsDelta_ShouldBuildSyncerAndExecuteSync() { - // // preparation - // final SphereClient sourceClient = mock(SphereClient.class); - // when(sourceClient.getConfig()).thenReturn(SphereClientConfig.of("foo", "foo", "foo")); - // - // final SphereClient targetClient = mock(SphereClient.class); - // when(targetClient.getConfig()).thenReturn(SphereClientConfig.of("bar", "bar", "bar")); - // - // when(sourceClient.execute(any(ProductProjectionQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // when(sourceClient.execute(any(ShoppingListQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // - // final ZonedDateTime currentCtpTimestamp = ZonedDateTime.now(); - // stubClientsCustomObjectService(targetClient, currentCtpTimestamp); - // - // final SyncerFactory syncerFactory = - // SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock()); - // - // // test - // String[] syncModuleOptions = {"products", "shoppingLists"}; - // syncerFactory.sync(syncModuleOptions, null, false, false, null).join(); - // - // // assertions - // verifyTimestampGeneratorCustomObjectUpsertIsCalled( - // targetClient, "ProductSync", DEFAULT_RUNNER_NAME); - // verifyTimestampGeneratorCustomObjectUpsertIsCalled( - // targetClient, "ShoppingListSync", DEFAULT_RUNNER_NAME); - // verify(targetClient, times(4)).execute(any(CustomObjectUpsertCommand.class)); - // verifyLastSyncCustomObjectQuery(targetClient, "productSync", DEFAULT_RUNNER_NAME, "foo", 1); - // verifyLastSyncCustomObjectQuery( - // targetClient, "shoppingListSync", DEFAULT_RUNNER_NAME, "foo", 1); - // verify(sourceClient, times(1)).execute(any(ProductProjectionQuery.class)); - // verify(sourceClient, times(1)).execute(any(ShoppingListQuery.class)); - // verifyInteractionsWithClientAfterSync(sourceClient, 2); - // - // assertProductSyncerLoggingEvents(productSyncerTestLogger, 0); - // assertShoppingListSyncerLoggingEvents(shoppingListSyncerTestLogger, 0); - // assertThat(productSyncerTestLogger.getAllLoggingEvents()).hasSize(2); - // assertThat(shoppingListSyncerTestLogger.getAllLoggingEvents()).hasSize(2); - // } - // - // @Test - // void sync_AsDelta_WithOneUnmatchedSyncOptionValue_ShouldResultIllegalArgumentException() { - // final SphereClient sourceClient = mock(SphereClient.class); - // when(sourceClient.getConfig()).thenReturn(SphereClientConfig.of("foo", "foo", "foo")); - // - // final SphereClient targetClient = mock(SphereClient.class); - // when(targetClient.getConfig()).thenReturn(SphereClientConfig.of("bar", "bar", "bar")); - // - // final SyncerFactory syncerFactory = - // SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock()); - // - // // test - // String[] syncResources = {"productTypes", "unknown", "shoppingLists"}; - // CompletionStage result = syncerFactory.sync(syncResources, null, false, false, null); - // - // String errorMessage = - // format( - // "Unknown argument \"%s\" supplied to \"-s\" or \"--sync\" option! %s", - // syncResources[1], SYNC_MODULE_OPTION_DESCRIPTION); - // - // assertThat(result) - // .failsWithin(1, TimeUnit.SECONDS) - // .withThrowableOfType(ExecutionException.class) - // .withCauseExactlyInstanceOf(CliException.class) - // .withMessageContaining(errorMessage); - // } - // - // @Test - // void sync_AsDelta_WithSyncOptionValuesAndAll_ShouldResultIllegalArgumentException() { - // final SphereClient sourceClient = mock(SphereClient.class); - // when(sourceClient.getConfig()).thenReturn(SphereClientConfig.of("foo", "foo", "foo")); - // - // final SphereClient targetClient = mock(SphereClient.class); - // when(targetClient.getConfig()).thenReturn(SphereClientConfig.of("bar", "bar", "bar")); - // - // final SyncerFactory syncerFactory = - // SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock()); - // - // // test - // String[] syncResources = {"productTypes", "all", "shoppingLists"}; - // CompletionStage result = syncerFactory.sync(syncResources, null, false, false, null); - // - // String errorMessage = - // format( - // "Wrong arguments supplied to \"-s\" or \"--sync\" option! " - // + "'all' option cannot be passed along with other arguments.\" %s", - // SYNC_MODULE_OPTION_DESCRIPTION); - // - // assertThat(result) - // .failsWithin(1, TimeUnit.SECONDS) - // .withThrowableOfType(ExecutionException.class) - // .withCauseExactlyInstanceOf(CliException.class) - // .withMessageContaining(errorMessage); - // } + private ProjectApiRoot mockClientResourceRequests(final String projectKey) { + return withTestClient( + projectKey, + (uri, method, encodedRequetsBody) -> { + final String responseString = "{\"results\":[]}"; + if (uri.contains("product-types") && ApiHttpMethod.GET.equals(method)) { + verifyProductTypesGetCounter.incrementAndGet(); + } + if (uri.contains("types") && ApiHttpMethod.GET.equals(method)) { + verifyTypesGetCounter.incrementAndGet(); + } + if (uri.contains("states") && ApiHttpMethod.GET.equals(method)) { + verifyStatesGetCounter.incrementAndGet(); + } + if (uri.contains("tax-categories") && ApiHttpMethod.GET.equals(method)) { + verifyTaxCategoriesGetCounter.incrementAndGet(); + } + if (uri.contains("categories") && ApiHttpMethod.GET.equals(method)) { + verifyCategoriesGetCounter.incrementAndGet(); + } + if (uri.contains("inventory?") && ApiHttpMethod.GET.equals(method)) { + verifyInventoryGetCounter.incrementAndGet(); + } + if (uri.contains("product-projections") && ApiHttpMethod.GET.equals(method)) { + verifyProductProjectionsGetCounter.incrementAndGet(); + } + if (uri.contains("cart-discounts") && ApiHttpMethod.GET.equals(method)) { + verifyCartDiscountsGetCounter.incrementAndGet(); + } + if (uri.contains("custom-objects") && ApiHttpMethod.GET.equals(method)) { + verifyCustomObjectsGetCounter.incrementAndGet(); + } + if (uri.contains("customers") && ApiHttpMethod.GET.equals(method)) { + verifyCustomersGetCounter.incrementAndGet(); + } + if (uri.contains("shopping-lists") && ApiHttpMethod.GET.equals(method)) { + verifyShoppingListsGetCounter.incrementAndGet(); + } + verifyInvokeClientCounter.incrementAndGet(); + return CompletableFuture.completedFuture( + new ApiHttpResponse<>(200, null, responseString.getBytes(StandardCharsets.UTF_8))); + }); + } + + @Test + void sync_WithNullOptionValue_ShouldCompleteExceptionallyWithIllegalArgumentException() { + assertThat( + SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock()) + .sync(new String[] {null}, "myRunnerName", false, false, null)) + .failsWithin(1, TimeUnit.SECONDS) + .withThrowableOfType(ExecutionException.class) + .withCauseExactlyInstanceOf(CliException.class) + .withMessageContaining( + format( + "Blank argument supplied to \"-s\" or \"--sync\" option! %s", + SYNC_MODULE_OPTION_DESCRIPTION)); + } + + @Test + void sync_WithEmptyOptionValue_ShouldCompleteExceptionallyWithIllegalArgumentException() { + assertThat( + SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock()) + .sync(new String[] {""}, "myRunnerName", false, false, null)) + .failsWithin(1, TimeUnit.SECONDS) + .withThrowableOfType(ExecutionException.class) + .withCauseExactlyInstanceOf(CliException.class) + .withMessageContaining( + format( + "Blank argument supplied to \"-s\" or \"--sync\" option! %s", + SYNC_MODULE_OPTION_DESCRIPTION)); + } + + @Test + void sync_WithUnknownOptionValue_ShouldCompleteExceptionallyWithIllegalArgumentException() { + final String[] unknownOptionValue = {"anyOption"}; + + assertThat( + SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock()) + .sync(unknownOptionValue, "myRunnerName", false, false, null)) + .failsWithin(1, TimeUnit.SECONDS) + .withThrowableOfType(ExecutionException.class) + .withCauseExactlyInstanceOf(CliException.class) + .withMessageContaining( + format( + "Unknown argument \"%s\" supplied to \"-s\" or \"--sync\" option! %s", + unknownOptionValue[0], SYNC_MODULE_OPTION_DESCRIPTION)); + } + + @Test + @SuppressWarnings("unchecked") + void sync_AsProductsDeltaSync_ShouldBuildSyncerAndExecuteSync() { + // preparation + final ProjectApiRoot sourceClientSpy = spy(sourceClient); + final ZonedDateTime currentCtpTimestamp = ZonedDateTime.now(); + final ProjectApiRoot targetClientMock = mock(ProjectApiRoot.class); + when(targetClientMock.getProjectKey()).thenReturn("testProjectKey"); + stubClientsCustomObjectService(targetClientMock, currentCtpTimestamp); + + final SyncerFactory syncerFactory = + SyncerFactory.of(() -> sourceClientSpy, () -> targetClientMock, getMockedClock()); + + // test + syncerFactory.sync(new String[] {"products"}, "myRunnerName", false, false, null); + + // assertions + // verify product-projections are queried once + verify(sourceClientSpy, times(1)).productProjections(); + assertThat(verifyProductProjectionsGetCounter.get()).isEqualTo(1); + verifyTimestampGeneratorCustomObjectUpsertIsCalled( + targetClientMock, "ProductSync", "myRunnerName"); + verifyLastSyncCustomObjectQuery( + targetClientMock, "productSync", "myRunnerName", "testProjectKey", 1); + // verify two custom object upserts : 1. current ctp timestamp and 2. last sync timestamp + // creation) + verify(targetClientMock.customObjects(), times(2)).post(any(CustomObjectDraft.class)); + // TODO: Assert on actual last sync timestamp creation in detail after Statistics classes in + // java-sync library + // TODO: override #equals method: + // https://github.com/commercetools/commercetools-sync-java/issues/376 + // TODO: e.g. verifyNewLastSyncCustomObjectCreation(targetClient, + // currentCtpTimestamp.minusMinutes(2), any(ProductSyncStatistics.class), 0L, "productSync", + // "foo"); + verifyInteractionsWithClientAfterSync(sourceClientSpy, 1); + + final Condition startLog = + new Condition<>( + loggingEvent -> + Level.INFO.equals(loggingEvent.getLevel()) + && loggingEvent.getMessage().contains("Starting ProductSync"), + "start log"); + + final Condition statisticsLog = + new Condition<>( + loggingEvent -> + Level.INFO.equals(loggingEvent.getLevel()) + && loggingEvent + .getMessage() + .contains( + "Summary: 0 product(s) were processed in total (0 created, 0 updated, " + + "0 failed to sync and 0 product(s) with missing reference(s))."), + "statistics log"); + + assertThat(productSyncerTestLogger.getAllLoggingEvents()) + .hasSize(2) + .haveExactly(1, startLog) + .haveExactly(1, statisticsLog); + } + + @Test + @SuppressWarnings("unchecked") + void sync_AsProductsFullSync_ShouldBuildSyncerAndExecuteSync() { + // preparation + final ProjectApiRoot sourceClientSpy = spy(sourceClient); + final ZonedDateTime currentCtpTimestamp = ZonedDateTime.now(); + final ProjectApiRoot targetClient = mock(ProjectApiRoot.class); + when(targetClient.getProjectKey()).thenReturn("testTargetProjectKey"); + stubClientsCustomObjectService(targetClient, currentCtpTimestamp); + + final SyncerFactory syncerFactory = + SyncerFactory.of(() -> sourceClientSpy, () -> targetClient, getMockedClock()); + + // test + syncerFactory.sync(new String[] {"products"}, "myRunnerName", true, false, null); + + // assertions + verify(sourceClientSpy, times(1)).productProjections(); + assertThat(verifyProductProjectionsGetCounter.get()).isEqualTo(1); + + verifyTimestampGeneratorCustomObjectUpsertIsNotCalled( + targetClient, "ProductSync", "myRunnerName"); + verifyLastSyncCustomObjectQuery(targetClient, "productSync", "myRunnerName", "foo", 0); + verify(targetClient.customObjects(), times(0)).post(any(CustomObjectDraft.class)); + verifyInteractionsWithClientAfterSync(sourceClientSpy, 1); + + final Condition startLog = + new Condition<>( + loggingEvent -> + Level.INFO.equals(loggingEvent.getLevel()) + && loggingEvent.getMessage().contains("Starting ProductSync"), + "start log"); + + final Condition statisticsLog = + new Condition<>( + loggingEvent -> + Level.INFO.equals(loggingEvent.getLevel()) + && loggingEvent + .getMessage() + .contains( + "Summary: 0 product(s) were processed in total (0 created, 0 updated, " + + "0 failed to sync and 0 product(s) with missing reference(s))."), + "statistics log"); + + assertThat(productSyncerTestLogger.getAllLoggingEvents()) + .hasSize(2) + .haveExactly(1, startLog) + .haveExactly(1, statisticsLog); + } + + @Test + void + sync_AsProductsFullSyncWithExceptionDuringAttributeReferenceReplacement_ShouldBuildSyncerAndExecuteSync() { + // preparation + final ProductProjection product5 = + ProductMixin.toProjection( + readObjectFromResource("product-key-5.json", Product.class), + ProductProjectionType.STAGED); + final ProductProjection product6 = + ProductMixin.toProjection( + readObjectFromResource("product-key-6.json", Product.class), + ProductProjectionType.STAGED); + final ProductProjectionPagedQueryResponse twoProductResult = + ProductProjectionPagedQueryResponseBuilder.of() + .results(product5, product6) + .limit(10L) + .count(2L) + .offset(0L) + .total(2L) + .build(); + + final BadGatewayException badGatewayException = createBadGatewayException(); + final ProjectApiRoot sourceClient = + withTestClient( + "testProjectKey", + (uri, method, encodedRequetsBody) -> { + if (uri.contains("graphql") && ApiHttpMethod.POST.equals(method)) { + return CompletableFutureUtils.failed(badGatewayException); + } + verifyInvokeClientCounter.incrementAndGet(); + if (uri.contains("product-projections") && ApiHttpMethod.GET.equals(method)) { + if (verifyProductProjectionsGetCounter.get() == 0) { + verifyProductProjectionsGetCounter.incrementAndGet(); + final String jsonString = + createJsonStringFromPagedQueryResponse(twoProductResult); + return CompletableFuture.completedFuture( + new ApiHttpResponse<>( + 200, null, jsonString.getBytes(StandardCharsets.UTF_8))); + } + } + return null; + }); + + final ProjectApiRoot targetClient = mock(ProjectApiRoot.class); + when(targetClient.getProjectKey()).thenReturn("testTargetProjectKey"); + stubClientsCustomObjectService(targetClient, ZonedDateTime.now()); + final ByProjectKeyProductsPost byProjectKeyProductsPost = mock(ByProjectKeyProductsPost.class); + when(byProjectKeyProductsPost.execute()) + .thenReturn(CompletableFutureUtils.failed(badGatewayException)); + when(targetClient.products()).thenReturn(mock()); + when(targetClient.products().post(any(ProductDraft.class))) + .thenReturn(byProjectKeyProductsPost); + + final ProjectApiRoot sourceSpy = spy(sourceClient); + final SyncerFactory syncerFactory = + SyncerFactory.of(() -> sourceSpy, () -> targetClient, getMockedClock()); + + // test + syncerFactory.sync(new String[] {"products"}, "myRunnerName", true, false, null); + + // assertions + verify(sourceSpy, times(1)).productProjections(); + verify(sourceSpy, times(3)).graphql(); + verifyInteractionsWithClientAfterSync(sourceSpy, 1); + + final Condition startLog = + new Condition<>( + loggingEvent -> + Level.INFO.equals(loggingEvent.getLevel()) + && loggingEvent.getMessage().contains("Starting ProductSync"), + "start log"); + + final Condition statisticsLog = + new Condition<>( + loggingEvent -> + Level.INFO.equals(loggingEvent.getLevel()) + && loggingEvent + .getMessage() + .contains( + "Summary: 0 product(s) were processed in total (0 created, 0 updated, " + + "0 failed to sync and 0 product(s) with missing reference(s))."), + "statistics log"); + + assertThat(productSyncerTestLogger.getAllLoggingEvents()) + .hasSize(3) + .haveExactly(1, startLog) + .haveExactly(1, statisticsLog); + + assertThat(productSyncerTestLogger.getAllLoggingEvents()) + .anySatisfy( + loggingEvent -> { + assertThat(loggingEvent.getMessage()) + .contains( + ReferenceTransformException.class.getCanonicalName() + + ": Failed to replace referenced resource ids with keys on the attributes of the " + + "products in the current fetched page from the source project. " + + "This page will not be synced to the target project."); + assertThat(loggingEvent.getThrowable().isPresent()).isTrue(); + assertThat(loggingEvent.getThrowable().get().getCause().getCause()) + .isEqualTo(badGatewayException); + }); + } + + // TODO: Enable test when issue with java-sync (NPE) is solved. + // See https://github.com/commercetools/commercetools-sync-java/issues/1101 + @Disabled + @Test + void + sync_AsProductsFullSyncWithExceptionDuringAttributeReferenceReplacement_ShouldContinueWithPages() { + // preparation + final AtomicInteger sourceGraphQLPostCounter = new AtomicInteger(0); + final ProductProjection product1 = + ProductMixin.toProjection( + readObjectFromResource("product-key-7.json", Product.class), + ProductProjectionType.STAGED); + final ProductProjection product2 = + ProductMixin.toProjection( + readObjectFromResource("product-key-8.json", Product.class), + ProductProjectionType.STAGED); + final ProductProjection product3 = + ProductMixin.toProjection( + readObjectFromResource("product-key-9.json", Product.class), + ProductProjectionType.STAGED); + + final List fullPageOfProducts = + IntStream.range(0, 500).mapToObj(o -> product1).collect(Collectors.toList()); + + final Long pageSize = Long.valueOf(fullPageOfProducts.size()); + + final ProductProjectionPagedQueryResponse fullPageResponse = + ProductProjectionPagedQueryResponseBuilder.of() + .results(fullPageOfProducts) + .limit(10L) + .count(pageSize) + .offset(0L) + .total(pageSize) + .build(); + final ProductProjectionPagedQueryResponse twoProductResult = + ProductProjectionPagedQueryResponseBuilder.of() + .results(product3, product2) + .limit(10L) + .count(2L) + .offset(0L) + .total(2L) + .build(); + + final ProjectApiRoot srcClient = + withTestClient( + "testProjectKey", + (uri, method, encodedRequestBody) -> { + final Charset charsetUTF8 = Charset.forName(StandardCharsets.UTF_8.name()); + if (uri.contains("graphql") && ApiHttpMethod.POST.equals(method)) { + final ObjectMapper objectMapper = JsonUtils.getConfiguredObjectMapper(); + GraphQLRequest graphQLRequest; + try { + graphQLRequest = objectMapper.readValue(encodedRequestBody, GraphQLRequest.class); + } catch (JsonProcessingException e) { + graphQLRequest = GraphQLRequestBuilder.of().build(); + } + final String graphQLRequestQuery = graphQLRequest.getQuery(); + final String bodyData = "{\"data\": %s}"; + String result = String.format(bodyData, "{}"); + if (graphQLRequestQuery != null) { + int graphQlPostCounter = sourceGraphQLPostCounter.getAndIncrement(); + if (graphQlPostCounter < 3) { + return CompletableFutureUtils.failed(createBadGatewayException()); + } + if (graphQLRequestQuery.contains("products")) { + final String jsonAsString = + "{\"results\":[{\"id\":\"53c4a8b4-865f-4b95-b6f2-3e1e70e3d0c1\",\"key\":\"productKey3\"}]}"; + result = String.format(bodyData, jsonAsString); + return CompletableFuture.completedFuture( + new ApiHttpResponse<>(200, null, result.getBytes(charsetUTF8))); + } else if (graphQLRequestQuery.contains("productTypes")) { + final String jsonAsString = + "{\"results\":[{\"id\":\"53c4a8b4-865f-4b95-b6f2-3e1e70e3d0c2\",\"key\":\"prodType1\"}]}"; + result = String.format(bodyData, jsonAsString); + return CompletableFuture.completedFuture( + new ApiHttpResponse<>(200, null, result.getBytes(charsetUTF8))); + } else if (graphQLRequestQuery.contains("categories")) { + final String jsonAsString = + "{\"results\":[{\"id\":\"53c4a8b4-865f-4b95-b6f2-3e1e70e3d0c3\",\"key\":\"cat1\"}]}"; + result = String.format(bodyData, jsonAsString); + return CompletableFuture.completedFuture( + new ApiHttpResponse<>(200, null, result.getBytes(charsetUTF8))); + } else { + return CompletableFuture.completedFuture( + new ApiHttpResponse<>(200, null, result.getBytes(charsetUTF8))); + } + } + } + if (uri.contains("product-projections") && ApiHttpMethod.GET.equals(method)) { + int sourceGetCounter = verifyProductProjectionsGetCounter.getAndIncrement(); + if (sourceGetCounter == 0) { + final String fullPageResponseAsString = + createJsonStringFromPagedQueryResponse(fullPageResponse); + return CompletableFuture.completedFuture( + new ApiHttpResponse<>( + 200, null, fullPageResponseAsString.getBytes(charsetUTF8))); + } else if (sourceGetCounter == 1) { + final String twoResultsResponseAsString = + createJsonStringFromPagedQueryResponse(twoProductResult); + return CompletableFuture.completedFuture( + new ApiHttpResponse<>( + 200, null, twoResultsResponseAsString.getBytes(charsetUTF8))); + + } else { + final String emptyResultsAsString = "{\"results\":[]}"; + return CompletableFuture.completedFuture( + new ApiHttpResponse<>(200, null, emptyResultsAsString.getBytes(charsetUTF8))); + } + } + return null; + }); + + final ProjectApiRoot trgClient = + ApiRootBuilder.of( + request -> { + final String uri = request.getUri() != null ? request.getUri().toString() : ""; + final ApiHttpMethod method = request.getMethod(); + final Charset charsetUTF8 = Charset.forName(StandardCharsets.UTF_8.name()); + if (uri.contains("graphql") && ApiHttpMethod.POST.equals(method)) { + final String encodedRequestBody = + new String(request.getBody(), StandardCharsets.UTF_8); + ObjectMapper objectMapper = JsonUtils.getConfiguredObjectMapper(); + GraphQLRequest graphQLRequest; + try { + graphQLRequest = + objectMapper.readValue(encodedRequestBody, GraphQLRequest.class); + } catch (JsonProcessingException e) { + graphQLRequest = GraphQLRequestBuilder.of().build(); + } + final String graphQLRequestQuery = graphQLRequest.getQuery(); + final String bodyData = "{\"data\": %s}"; + String result; + if (graphQLRequestQuery != null) { + if (graphQLRequestQuery.contains("products")) { + final String jsonAsString = + "{\"results\":[{\"id\":\"53c4a8b4-865f-4b95-b6f2-3e1e70e3d0c1\",\"key\":\"productKey3\"}]}"; + result = String.format(bodyData, jsonAsString); + return CompletableFuture.completedFuture( + new ApiHttpResponse<>(200, null, result.getBytes(charsetUTF8))); + } else { + result = String.format(bodyData, "{\"results\": []}"); + return CompletableFuture.completedFuture( + new ApiHttpResponse<>(200, null, result.getBytes(charsetUTF8))); + } + } + } + if (uri.contains("products") && ApiHttpMethod.POST.equals(method)) { + final String productsResultAsString = readStringFromFile("product-key-8.json"); + return CompletableFuture.completedFuture( + new ApiHttpResponse<>( + 200, null, productsResultAsString.getBytes(charsetUTF8))); + + } else { + final String emptyResultsAsString = "{\"results\":[]}"; + return CompletableFuture.completedFuture( + new ApiHttpResponse<>( + 200, null, emptyResultsAsString.getBytes(charsetUTF8))); + } + }) + .withApiBaseUrl("testBaseUrl") + .build("testProjectKey2"); + + final ProjectApiRoot sourceClientSpy = spy(srcClient); + final ProjectApiRoot targetClientSpy = spy(trgClient); + + final SyncerFactory syncerFactory = + SyncerFactory.of(() -> sourceClientSpy, () -> targetClientSpy, getMockedClock()); + + // test + syncerFactory.sync(new String[] {"products"}, "myRunnerName", true, false, null); + + // assertions + assertThat(verifyProductProjectionsGetCounter.get()).isEqualTo(2); + verify(sourceClientSpy, times(9)).graphql(); + verifyInteractionsWithClientAfterSync(sourceClientSpy, 1); + + final Condition startLog = + new Condition<>( + loggingEvent -> + Level.INFO.equals(loggingEvent.getLevel()) + && loggingEvent.getMessage().contains("Starting ProductSync"), + "start log"); + + final Condition statisticsLog = + new Condition<>( + loggingEvent -> + Level.INFO.equals(loggingEvent.getLevel()) + && loggingEvent + .getMessage() + .contains( + "Summary: 2 product(s) were processed in total (2 created, 0 updated, " + + "0 failed to sync and 0 product(s) with missing reference(s))."), + "statistics log"); + + assertThat(productSyncerTestLogger.getAllLoggingEvents()) + .hasSize(3) + .haveExactly(1, startLog) + .haveExactly(1, statisticsLog); + + assertThat(productSyncerTestLogger.getAllLoggingEvents()) + .anySatisfy( + loggingEvent -> { + assertThat(loggingEvent.getMessage()) + .contains( + ReferenceTransformException.class.getCanonicalName() + + ": Failed to replace referenced resource ids with keys on the attributes of the " + + "products in the current fetched page from the source project. " + + "This page will not be synced to the target project."); + assertThat(loggingEvent.getThrowable().isPresent()).isTrue(); + assertThat(loggingEvent.getThrowable().get().getCause().getCause()) + .isInstanceOf(BadGatewayException.class); + }); + } + + private static void verifyTimestampGeneratorCustomObjectUpsertIsCalled( + @Nonnull final ProjectApiRoot client, + @Nonnull final String syncMethodName, + @Nonnull final String syncRunnerName) { + final CustomObjectDraft customObjectDraft = + findTimestampGeneratorCustomObjectUpsert(client, syncMethodName, syncRunnerName); + assertThat(customObjectDraft).isNotNull(); + assertThat((String) customObjectDraft.getValue()) + .matches( + "[0-9a-fA-F]{8}\\-[0-9a-fA-F]{4}\\-[0-9a-fA-F]{4}\\-[0-9a-fA-F]{4}\\-[0-9a-fA-F]{12}"); + } + + private static void verifyTimestampGeneratorCustomObjectUpsertIsNotCalled( + @Nonnull final ProjectApiRoot client, + @Nonnull final String syncMethodName, + @Nonnull final String syncRunnerName) { + final CustomObjectDraft customObjectDraft = + findTimestampGeneratorCustomObjectUpsert(client, syncMethodName, syncRunnerName); + assertThat(customObjectDraft).isNull(); + } + + private static CustomObjectDraft findTimestampGeneratorCustomObjectUpsert( + @Nonnull ProjectApiRoot client, + @Nonnull String syncMethodName, + @Nonnull String syncRunnerName) { + // fact: SphereRequest is a very broad interface and we actually wanted to capture only + // CustomObjectUpsertCommand. + // I tried it but argumentcaptor captures also CustomObjectQueryImpl classes, because we call + // both query and upsert in the mocked ProjectApiRoot. + // This situation throws runtime NPE error later in the method as query doesnt contain a draft. + // I guess generics doesnt work here as type is not know on compile time. + // That's why we need to filter instanceof CustomObjectUpsertCommand in the streams. + final ArgumentCaptor customObjectDraftArgumentCaptor = + ArgumentCaptor.forClass(CustomObjectDraft.class); + + verify(client.customObjects(), atLeast(0)).post(customObjectDraftArgumentCaptor.capture()); + final List allValues = customObjectDraftArgumentCaptor.getAllValues(); + final CustomObjectDraft customObjectDraft = + allValues.stream() + .filter(draft -> draft instanceof CustomObjectDraft) + .filter( + draft -> + draft + .getContainer() + .equals( + format( + "%s.%s.%s.%s", + getApplicationName(), + syncRunnerName, + syncMethodName, + TIMESTAMP_GENERATOR_KEY)) + && draft.getKey().equals(TIMESTAMP_GENERATOR_KEY)) + .findAny() + .orElse(null); + return customObjectDraft; + } + + private static void verifyLastSyncCustomObjectQuery( + @Nonnull final ProjectApiRoot client, + @Nonnull final String syncModuleName, + @Nonnull final String syncRunnerName, + @Nonnull final String sourceProjectKey, + final int expectedInvocations) { + + final String container = + format("commercetools-project-sync.%s.%s", syncRunnerName, syncModuleName); + + if (expectedInvocations > 0) { + verify(client.customObjects(), times(expectedInvocations)) + .withContainerAndKey(container, sourceProjectKey); + } else { + verifyNoInteractions( + client.customObjects().withContainerAndKey(anyString(), anyString()).get()); + } + } + + private static String createJsonStringFromPagedQueryResponse( + final ResourcePagedQueryResponse pagedQueryResponse) { + try { + return JsonUtils.toJsonString(pagedQueryResponse); + } catch (JsonProcessingException e) { + return "{\"results\": []}"; + } + } + + @Test + @SuppressWarnings("unchecked") + void sync_AsCategoriesDeltaSync_ShouldBuildSyncerAndExecuteSync() { + // preparation + final ProjectApiRoot sourceClient = mockClientResourceRequests("testSourceProjectKey"); + final ZonedDateTime currentCtpTimestamp = ZonedDateTime.now(); + final ProjectApiRoot targetClient = mock(ProjectApiRoot.class); + when(targetClient.getProjectKey()).thenReturn("testTargetProjectKey"); + stubClientsCustomObjectService(targetClient, currentCtpTimestamp); + + final SyncerFactory syncerFactory = + SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock()); + // test + syncerFactory.sync(new String[] {"categories"}, null, false, false, null); + + // assertions + assertThat(verifyCategoriesGetCounter.get()).isEqualTo(1); + verifyTimestampGeneratorCustomObjectUpsertIsCalled( + targetClient, "CategorySync", DEFAULT_RUNNER_NAME); + verifyLastSyncCustomObjectQuery( + targetClient, "categorySync", DEFAULT_RUNNER_NAME, "testSourceProjectKey", 1); + // verify two custom object upserts : 1. current ctp timestamp and 2. last sync timestamp + verify(targetClient.customObjects(), times(2)).post(any(CustomObjectDraft.class)); + // TODO: Assert on actual last sync timestamp creation in detail after Statistics classes in + // java-sync library + // TODO: override #equals method: + // https://github.com/commercetools/commercetools-sync-java/issues/376 + // TODO: e.g. verifyNewLastSyncCustomObjectCreation(targetClient, + // currentCtpTimestamp.minusMinutes(2), any(ProductSyncStatistics.class), 0L, "productSync", + // "foo"); + assertThat(verifyInvokeClientCounter.get()).isEqualTo(1); + + final Condition startLog = + new Condition<>( + loggingEvent -> + Level.INFO.equals(loggingEvent.getLevel()) + && loggingEvent.getMessage().contains("Starting CategorySync"), + "start log"); + + final Condition statisticsLog = + new Condition<>( + loggingEvent -> + Level.INFO.equals(loggingEvent.getLevel()) + && loggingEvent + .getMessage() + .contains( + "Summary: 0 categories were processed in total (0 created, 0 updated, " + + "0 failed to sync and 0 categories with a missing parent)."), + "statistics log"); + + assertThat(categorySyncerTestLogger.getAllLoggingEvents()) + .hasSize(2) + .haveExactly(1, startLog) + .haveExactly(1, statisticsLog); + } + + @Test + @SuppressWarnings("unchecked") + void sync_AsProductTypesDeltaSync_ShouldBuildSyncerAndExecuteSync() { + // preparation + final ProjectApiRoot sourceClient = mockClientResourceRequests("testSourceProjectKey"); + final ZonedDateTime currentCtpTimestamp = ZonedDateTime.now(); + final ProjectApiRoot targetClient = mock(ProjectApiRoot.class); + when(targetClient.getProjectKey()).thenReturn("testTargetProjectKey"); + stubClientsCustomObjectService(targetClient, currentCtpTimestamp); + + final SyncerFactory syncerFactory = + SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock()); + + // test + syncerFactory.sync(new String[] {"productTypes"}, "", false, false, null); + + // assertions + assertThat(verifyProductTypesGetCounter.get()).isEqualTo(1); + verifyTimestampGeneratorCustomObjectUpsertIsCalled( + targetClient, "ProductTypeSync", DEFAULT_RUNNER_NAME); + verifyLastSyncCustomObjectQuery( + targetClient, "productTypeSync", DEFAULT_RUNNER_NAME, "testSourceProjectKey", 1); + // verify two custom object upserts : 1. current ctp timestamp and 2. last sync timestamp + // creation) + verify(targetClient.customObjects(), times(2)).post(any(CustomObjectDraft.class)); + // TODO: Assert on actual last sync timestamp creation in detail after Statistics classes in + // java-sync library + // TODO: override #equals method: + // https://github.com/commercetools/commercetools-sync-java/issues/376 + // TODO: e.g. verifyNewLastSyncCustomObjectCreation(targetClient, + // currentCtpTimestamp.minusMinutes(2), any(ProductSyncStatistics.class), 0L, "productSync", + // "foo"); + assertThat(verifyInvokeClientCounter.get()).isEqualTo(1); + + final Condition startLog = + new Condition<>( + loggingEvent -> + Level.INFO.equals(loggingEvent.getLevel()) + && loggingEvent.getMessage().contains("Starting ProductTypeSync"), + "start log"); + + final Condition statisticsLog = + new Condition<>( + loggingEvent -> + Level.INFO.equals(loggingEvent.getLevel()) + && loggingEvent + .getMessage() + .contains( + "Summary: 0 product types were processed in total (0 created, 0 updated, 0 failed to sync" + + " and 0 product types with at least one NestedType or a Set of NestedType attribute" + + " definition(s) referencing a missing product type)."), + "statistics log"); + + assertThat(productTypeSyncerTestLogger.getAllLoggingEvents()) + .hasSize(2) + .haveExactly(1, startLog) + .haveExactly(1, statisticsLog); + } + + @Test + @SuppressWarnings("unchecked") + void sync_AsTypesDeltaSync_ShouldBuildSyncerAndExecuteSync() { + // preparation + final ProjectApiRoot sourceClient = mockClientResourceRequests("testSourceProjectKey"); + final ZonedDateTime currentCtpTimestamp = ZonedDateTime.now(); + final ProjectApiRoot targetClient = mock(ProjectApiRoot.class); + when(targetClient.getProjectKey()).thenReturn("testTargetProjectKey"); + stubClientsCustomObjectService(targetClient, currentCtpTimestamp); + + final SyncerFactory syncerFactory = + SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock()); + + // test + syncerFactory.sync(new String[] {"types"}, "foo", false, false, null); + + // assertions + assertThat(verifyTypesGetCounter.get()).isEqualTo(1); + verifyTimestampGeneratorCustomObjectUpsertIsCalled(targetClient, "TypeSync", "foo"); + verifyLastSyncCustomObjectQuery(targetClient, "typeSync", "foo", "testSourceProjectKey", 1); + // verify two custom object upserts : 1. current ctp timestamp and 2. last sync timestamp + // creation) + verify(targetClient.customObjects(), times(2)).post(any(CustomObjectDraft.class)); + // TODO: Assert on actual last sync timestamp creation in detail after Statistics classes in + // java-sync library + // TODO: override #equals method: + // https://github.com/commercetools/commercetools-sync-java/issues/376 + // TODO: e.g. verifyNewLastSyncCustomObjectCreation(targetClient, + // currentCtpTimestamp.minusMinutes(2), any(ProductSyncStatistics.class), 0L, "productSync", + // "foo"); + assertThat(verifyInvokeClientCounter.get()).isEqualTo(1); + + final Condition startLog = + new Condition<>( + loggingEvent -> + Level.INFO.equals(loggingEvent.getLevel()) + && loggingEvent.getMessage().contains("Starting TypeSync"), + "start log"); + + final Condition statisticsLog = + new Condition<>( + loggingEvent -> + Level.INFO.equals(loggingEvent.getLevel()) + && loggingEvent + .getMessage() + .contains( + "Summary: 0 types were processed in total (0 created, 0 updated " + + "and 0 failed to sync)."), + "statistics log"); + + assertThat(typeSyncerTestLogger.getAllLoggingEvents()) + .hasSize(2) + .haveExactly(1, startLog) + .haveExactly(1, statisticsLog); + } + + @Test + @SuppressWarnings("unchecked") + void sync_AsInventoryEntriesDeltaSync_ShouldBuildSyncerAndExecuteSync() { + // preparation + final ProjectApiRoot sourceClient = mockClientResourceRequests("testSourceProjectKey"); + final ZonedDateTime currentCtpTimestamp = ZonedDateTime.now(); + final ProjectApiRoot targetClient = mock(ProjectApiRoot.class); + when(targetClient.getProjectKey()).thenReturn("testTargetProjectKey"); + stubClientsCustomObjectService(targetClient, currentCtpTimestamp); + + final SyncerFactory syncerFactory = + SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock()); + + // test + syncerFactory.sync(new String[] {"inventoryEntries"}, null, false, false, null); + + // assertions + assertThat(verifyInventoryGetCounter.get()).isEqualTo(1); + verifyTimestampGeneratorCustomObjectUpsertIsCalled( + targetClient, "InventorySync", DEFAULT_RUNNER_NAME); + verifyLastSyncCustomObjectQuery( + targetClient, "inventorySync", DEFAULT_RUNNER_NAME, "testSourceProjectKey", 1); + // verify two custom object upserts : 1. current ctp timestamp and 2. last sync timestamp + // creation) + verify(targetClient.customObjects(), times(2)).post(any(CustomObjectDraft.class)); + // TODO: Assert on actual last sync timestamp creation in detail after Statistics classes in + // java-sync library + // TODO: override #equals method: + // https://github.com/commercetools/commercetools-sync-java/issues/376 + // TODO: e.g. verifyNewLastSyncCustomObjectCreation(targetClient, + // currentCtpTimestamp.minusMinutes(2), any(ProductSyncStatistics.class), 0L, "productSync", + // "foo"); + assertThat(verifyInvokeClientCounter.get()).isEqualTo(1); + + final Condition startLog = + new Condition<>( + loggingEvent -> + Level.INFO.equals(loggingEvent.getLevel()) + && loggingEvent.getMessage().contains("Starting InventorySync"), + "start log"); + + final Condition statisticsLog = + new Condition<>( + loggingEvent -> + Level.INFO.equals(loggingEvent.getLevel()) + && loggingEvent + .getMessage() + .contains( + "Summary: 0 inventory entries were processed in total (0 created, 0 updated " + + "and 0 failed to sync)."), + "statistics log"); + + assertThat(inventoryEntrySyncerTestLogger.getAllLoggingEvents()) + .hasSize(2) + .haveExactly(1, startLog) + .haveExactly(1, statisticsLog); + } + + @Test + void sync_WithErrorOnFetch_ShouldCloseClientAndCompleteExceptionally() { + // preparation + final ProjectApiRoot sourceClient = + withTestClient( + "testProjectKey", + (uri, method, encodedRequestBody) -> { + verifyInvokeClientCounter.incrementAndGet(); + if (uri.contains("inventory") && ApiHttpMethod.GET.equals(method)) { + verifyInventoryGetCounter.incrementAndGet(); + return CompletableFutureUtils.exceptionallyCompletedFuture( + createBadGatewayException()); + } + return null; + }); + + final ZonedDateTime currentCtpTimestamp = ZonedDateTime.now(); + final ProjectApiRoot targetClient = mock(ProjectApiRoot.class); + when(targetClient.getProjectKey()).thenReturn("testTargetProjectKey"); + stubClientsCustomObjectService(targetClient, currentCtpTimestamp); + + final SyncerFactory syncerFactory = + SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock()); + + // test + final CompletionStage result = + syncerFactory.sync(new String[] {"inventoryEntries"}, null, false, false, null); + + // assertions + verifyTimestampGeneratorCustomObjectUpsertIsCalled( + targetClient, "InventorySync", DEFAULT_RUNNER_NAME); + assertThat(verifyInventoryGetCounter.get()).isEqualTo(1); + assertThat(verifyInvokeClientCounter.get()).isEqualTo(1); + assertThat(result) + .failsWithin(1, TimeUnit.SECONDS) + .withThrowableOfType(ExecutionException.class) + .withCauseExactlyInstanceOf(BadGatewayException.class); + } + + @Test + @SuppressWarnings("unchecked") + void + sync_WithErrorOnCurrentCtpTimestampUpsert_ShouldCloseClientAndCompleteExceptionallyWithoutSyncing() { + // preparation + final ProjectApiRoot sourceClient = mockClientResourceRequests("testSourceProjectKey"); + ProjectApiRoot spy = spy(sourceClient); + final ProjectApiRoot targetClient = mock(ProjectApiRoot.class); + when(targetClient.getProjectKey()).thenReturn("testTargetProjectKey"); + final ByProjectKeyCustomObjectsPost customObjectsPost = + mock(ByProjectKeyCustomObjectsPost.class); + when(customObjectsPost.execute()) + .thenReturn( + CompletableFutureUtils.exceptionallyCompletedFuture(createBadGatewayException())); + when(targetClient.customObjects()).thenReturn(mock()); + when(targetClient.customObjects().post(any(CustomObjectDraft.class))) + .thenReturn(customObjectsPost); + + final SyncerFactory syncerFactory = + SyncerFactory.of(() -> spy, () -> targetClient, getMockedClock()); + + // test + final CompletionStage result = + syncerFactory.sync(new String[] {"inventoryEntries"}, "", false, false, null); + + // assertions + verifyTimestampGeneratorCustomObjectUpsertIsCalled( + targetClient, "InventorySync", DEFAULT_RUNNER_NAME); + assertThat(verifyInventoryGetCounter.get()).isEqualTo(0); + verifyInteractionsWithClientAfterSync(spy, 1); + assertThat(result) + .failsWithin(1, TimeUnit.SECONDS) + .withThrowableOfType(ExecutionException.class) + .withCauseExactlyInstanceOf(BadGatewayException.class); + } + + @Test + @SuppressWarnings("unchecked") + void + sync_WithErrorOnQueryLastSyncTimestamp_ShouldCloseClientAndCompleteExceptionallyWithoutSyncing() { + // preparation + final ProjectApiRoot sourceClientSpy = spy(sourceClient); + final ProjectApiRoot targetClient = mock(ProjectApiRoot.class); + when(targetClient.getProjectKey()).thenReturn("testTargetProjectKey"); + final ByProjectKeyCustomObjectsPost customObjectsPost = + mock(ByProjectKeyCustomObjectsPost.class); + final CustomObject lastSyncCustomObjectCustomObject = + mockLastSyncCustomObject(ZonedDateTime.now()); + final ApiHttpResponse apiHttpResponse = mock(ApiHttpResponse.class); + when(apiHttpResponse.getBody()).thenReturn(lastSyncCustomObjectCustomObject); + when(customObjectsPost.execute()) + .thenReturn(CompletableFuture.completedFuture(apiHttpResponse)); + when(targetClient.customObjects()).thenReturn(mock()); + when(targetClient.customObjects().withContainerAndKey(anyString(), anyString())) + .thenReturn(mock()); + when(targetClient.customObjects().withContainerAndKey(anyString(), anyString()).get()) + .thenReturn(mock()); + when(targetClient.customObjects().withContainerAndKey(anyString(), anyString()).get().execute()) + .thenReturn( + CompletableFutureUtils.exceptionallyCompletedFuture(createBadGatewayException())); + when(targetClient.customObjects().post(any(CustomObjectDraft.class))) + .thenReturn(customObjectsPost); + + final SyncerFactory syncerFactory = + SyncerFactory.of(() -> sourceClientSpy, () -> targetClient, getMockedClock()); + + // test + final CompletionStage result = + syncerFactory.sync(new String[] {"inventoryEntries"}, "bar", false, false, null); + + // assertions + verifyTimestampGeneratorCustomObjectUpsertIsCalled(targetClient, "InventorySync", "bar"); + verifyLastSyncCustomObjectQuery(targetClient, "inventorySync", "bar", "testProjectKey", 1); + verify(sourceClientSpy, times(0)).inventory(); + verifyInteractionsWithClientAfterSync(sourceClientSpy, 1); + assertThat(result) + .failsWithin(1, TimeUnit.SECONDS) + .withThrowableOfType(ExecutionException.class) + .withCauseExactlyInstanceOf(BadGatewayException.class); + } + + @Test + @SuppressWarnings("unchecked") + void syncAll_AsDelta_ShouldBuildSyncerAndExecuteSync() { + // preparation + final ProjectApiRoot sourceClientSpy = spy(sourceClient); + final ZonedDateTime currentCtpTimestamp = ZonedDateTime.now(); + final ProjectApiRoot targetClient = mock(ProjectApiRoot.class); + when(targetClient.getProjectKey()).thenReturn("testTargetProjectKey"); + stubClientsCustomObjectService(targetClient, currentCtpTimestamp); + final SyncerFactory syncerFactory = + SyncerFactory.of(() -> sourceClientSpy, () -> targetClient, getMockedClock()); + + // test + syncerFactory.sync(new String[] {"all"}, null, false, false, null).join(); + + // assertions + verifyTimestampGeneratorCustomObjectUpsertIsCalled( + targetClient, "ProductTypeSync", DEFAULT_RUNNER_NAME); + verifyTimestampGeneratorCustomObjectUpsertIsCalled( + targetClient, "ProductSync", DEFAULT_RUNNER_NAME); + verifyTimestampGeneratorCustomObjectUpsertIsCalled( + targetClient, "CategorySync", DEFAULT_RUNNER_NAME); + verifyTimestampGeneratorCustomObjectUpsertIsCalled( + targetClient, "TypeSync", DEFAULT_RUNNER_NAME); + verifyTimestampGeneratorCustomObjectUpsertIsCalled( + targetClient, "InventorySync", DEFAULT_RUNNER_NAME); + verifyTimestampGeneratorCustomObjectUpsertIsCalled( + targetClient, "CartDiscountSync", DEFAULT_RUNNER_NAME); + verifyTimestampGeneratorCustomObjectUpsertIsCalled( + targetClient, "StateSync", DEFAULT_RUNNER_NAME); + verifyTimestampGeneratorCustomObjectUpsertIsCalled( + targetClient, "TaxCategorySync", DEFAULT_RUNNER_NAME); + verifyTimestampGeneratorCustomObjectUpsertIsCalled( + targetClient, "CustomObjectSync", DEFAULT_RUNNER_NAME); + verifyTimestampGeneratorCustomObjectUpsertIsCalled( + targetClient, "CustomerSync", DEFAULT_RUNNER_NAME); + verifyTimestampGeneratorCustomObjectUpsertIsCalled( + targetClient, "ShoppingListSync", DEFAULT_RUNNER_NAME); + verify(targetClient.customObjects(), times(22)).post(any(CustomObjectDraft.class)); + verifyLastSyncCustomObjectQuery( + targetClient, "inventorySync", DEFAULT_RUNNER_NAME, "testProjectKey", 1); + verifyLastSyncCustomObjectQuery( + targetClient, "productTypeSync", DEFAULT_RUNNER_NAME, "testProjectKey", 1); + verifyLastSyncCustomObjectQuery( + targetClient, "productSync", DEFAULT_RUNNER_NAME, "testProjectKey", 1); + verifyLastSyncCustomObjectQuery( + targetClient, "categorySync", DEFAULT_RUNNER_NAME, "testProjectKey", 1); + verifyLastSyncCustomObjectQuery( + targetClient, "typeSync", DEFAULT_RUNNER_NAME, "testProjectKey", 1); + verifyLastSyncCustomObjectQuery( + targetClient, "cartDiscountSync", DEFAULT_RUNNER_NAME, "testProjectKey", 1); + verifyLastSyncCustomObjectQuery( + targetClient, "stateSync", DEFAULT_RUNNER_NAME, "testProjectKey", 1); + verifyLastSyncCustomObjectQuery( + targetClient, "taxCategorySync", DEFAULT_RUNNER_NAME, "testProjectKey", 1); + verifyLastSyncCustomObjectQuery( + targetClient, "customObjectSync", DEFAULT_RUNNER_NAME, "testProjectKey", 1); + verifyLastSyncCustomObjectQuery( + targetClient, "customerSync", DEFAULT_RUNNER_NAME, "testProjectKey", 1); + verifyLastSyncCustomObjectQuery( + targetClient, "shoppingListSync", DEFAULT_RUNNER_NAME, "testProjectKey", 1); + verify(sourceClientSpy, times(1)).productTypes(); + verify(sourceClientSpy, times(1)).types(); + verify(sourceClientSpy, times(1)).categories(); + verify(sourceClientSpy, times(1)).productProjections(); + verify(sourceClientSpy, times(1)).inventory(); + verify(sourceClientSpy, times(1)).cartDiscounts(); + verify(sourceClientSpy, times(1)).states(); + verify(sourceClientSpy, times(1)).taxCategories(); + verify(sourceClientSpy, times(1)).customObjects(); + verify(sourceClientSpy, times(1)).customers(); + verify(sourceClientSpy, times(1)).shoppingLists(); + verifyInteractionsWithClientAfterSync(sourceClientSpy, 11); + + assertThat(cliRunnerTestLogger.getAllLoggingEvents()) + .allMatch(loggingEvent -> !Level.ERROR.equals(loggingEvent.getLevel())); + + assertThat(productSyncerTestLogger.getAllLoggingEvents()) + .allMatch(loggingEvent -> !Level.ERROR.equals(loggingEvent.getLevel())); + + assertTypeSyncerLoggingEvents(typeSyncerTestLogger, 0); + assertProductTypeSyncerLoggingEvents(productTypeSyncerTestLogger, 0); + assertCategorySyncerLoggingEvents(categorySyncerTestLogger, 0); + assertProductSyncerLoggingEvents(productSyncerTestLogger, 0); + assertInventoryEntrySyncerLoggingEvents(inventoryEntrySyncerTestLogger, 0); + assertCartDiscountSyncerLoggingEvents(cartDiscountSyncerTestLogger, 0); + // +1 state is a built-in state and it cant be deleted + assertStateSyncerLoggingEvents(stateSyncerTestLogger, 0); + assertTaxCategorySyncerLoggingEvents(taxCategorySyncerTestLogger, 0); + assertCustomObjectSyncerLoggingEvents(customObjectSyncerTestLogger, 0); + assertCustomerSyncerLoggingEvents(customerSyncerTestLogger, 0); + assertShoppingListSyncerLoggingEvents(shoppingListSyncerTestLogger, 0); + + // Every sync module is expected to have 2 logs (start and stats summary) + assertThat(typeSyncerTestLogger.getAllLoggingEvents()).hasSize(2); + assertThat(productTypeSyncerTestLogger.getAllLoggingEvents()).hasSize(2); + assertThat(categorySyncerTestLogger.getAllLoggingEvents()).hasSize(2); + assertThat(productSyncerTestLogger.getAllLoggingEvents()).hasSize(2); + assertThat(inventoryEntrySyncerTestLogger.getAllLoggingEvents()).hasSize(2); + assertThat(cartDiscountSyncerTestLogger.getAllLoggingEvents()).hasSize(2); + assertThat(stateSyncerTestLogger.getAllLoggingEvents()).hasSize(2); + assertThat(taxCategorySyncerTestLogger.getAllLoggingEvents()).hasSize(2); + assertThat(customObjectSyncerTestLogger.getAllLoggingEvents()).hasSize(2); + assertThat(customerSyncerTestLogger.getAllLoggingEvents()).hasSize(2); + assertThat(shoppingListSyncerTestLogger.getAllLoggingEvents()).hasSize(2); + } + + @Test + @SuppressWarnings("unchecked") + void syncProductTypesProductsCustomersAndShoppingLists_AsDelta_ShouldBuildSyncerAndExecuteSync() { + // preparation + final ProjectApiRoot sourceClientSpy = spy(sourceClient); + final ZonedDateTime currentCtpTimestamp = ZonedDateTime.now(); + final ProjectApiRoot targetClient = mock(ProjectApiRoot.class); + when(targetClient.getProjectKey()).thenReturn("testTargetProjectKey"); + stubClientsCustomObjectService(targetClient, currentCtpTimestamp); + final SyncerFactory syncerFactory = + SyncerFactory.of(() -> sourceClientSpy, () -> targetClient, getMockedClock()); + + // test + String[] syncModuleOptions = {"productTypes", "products", "customers", "shoppingLists"}; + syncerFactory.sync(syncModuleOptions, null, false, false, null).join(); + + // assertions + verifyTimestampGeneratorCustomObjectUpsertIsCalled( + targetClient, "ProductTypeSync", DEFAULT_RUNNER_NAME); + verifyTimestampGeneratorCustomObjectUpsertIsCalled( + targetClient, "ProductSync", DEFAULT_RUNNER_NAME); + verifyTimestampGeneratorCustomObjectUpsertIsCalled( + targetClient, "CustomerSync", DEFAULT_RUNNER_NAME); + verifyTimestampGeneratorCustomObjectUpsertIsCalled( + targetClient, "ShoppingListSync", DEFAULT_RUNNER_NAME); + verify(targetClient.customObjects(), times(8)).post(any(CustomObjectDraft.class)); + verifyLastSyncCustomObjectQuery( + targetClient, "productTypeSync", DEFAULT_RUNNER_NAME, "testProjectKey", 1); + verifyLastSyncCustomObjectQuery( + targetClient, "productSync", DEFAULT_RUNNER_NAME, "testProjectKey", 1); + verifyLastSyncCustomObjectQuery( + targetClient, "customerSync", DEFAULT_RUNNER_NAME, "testProjectKey", 1); + verifyLastSyncCustomObjectQuery( + targetClient, "shoppingListSync", DEFAULT_RUNNER_NAME, "testProjectKey", 1); + + final InOrder inOrder = Mockito.inOrder(sourceClientSpy); + + // According to sync algorithm, ProductType and Customer will run sync in parallel, Product and + // ShoppingList sequentially. + // Example: Given: ['productTypes', 'customers', 'products', 'shoppingLists'] + // From the given arguments, algorithm will group the resources as below, + // [productTypes, customers] [products] [shoppingLists] + inOrder.verify(sourceClientSpy, times(1)).productTypes(); + verify(sourceClientSpy, times(1)).customers(); + inOrder.verify(sourceClientSpy, times(1)).productProjections(); + inOrder.verify(sourceClientSpy, times(1)).shoppingLists(); + assertThat(verifyProductTypesGetCounter.get()).isEqualTo(1); + assertThat(verifyCustomersGetCounter.get()).isEqualTo(1); + assertThat(verifyProductProjectionsGetCounter.get()).isEqualTo(1); + assertThat(verifyShoppingListsGetCounter.get()).isEqualTo(1); + verifyInteractionsWithClientAfterSync(sourceClientSpy, 4); + + assertProductTypeSyncerLoggingEvents(productTypeSyncerTestLogger, 0); + assertProductSyncerLoggingEvents(productSyncerTestLogger, 0); + assertCustomerSyncerLoggingEvents(customerSyncerTestLogger, 0); + assertShoppingListSyncerLoggingEvents(shoppingListSyncerTestLogger, 0); + } + + @Test + @SuppressWarnings("unchecked") + void syncStatesInventoryEntriesAndCustomObjects_AsDelta_ShouldBuildSyncerAndExecuteSync() { + // preparation + final ProjectApiRoot sourceClientSpy = spy(sourceClient); + final ZonedDateTime currentCtpTimestamp = ZonedDateTime.now(); + final ProjectApiRoot targetClient = mock(ProjectApiRoot.class); + when(targetClient.getProjectKey()).thenReturn("testTargetProjectKey"); + stubClientsCustomObjectService(targetClient, currentCtpTimestamp); + final SyncerFactory syncerFactory = + SyncerFactory.of(() -> sourceClientSpy, () -> targetClient, getMockedClock()); + + // test + String[] syncModuleOptions = {"states", "inventoryEntries", "customObjects"}; + syncerFactory.sync(syncModuleOptions, null, false, false, null).join(); + + // assertions + verifyTimestampGeneratorCustomObjectUpsertIsCalled( + targetClient, "StateSync", DEFAULT_RUNNER_NAME); + verifyTimestampGeneratorCustomObjectUpsertIsCalled( + targetClient, "InventorySync", DEFAULT_RUNNER_NAME); + verifyTimestampGeneratorCustomObjectUpsertIsCalled( + targetClient, "CustomObjectSync", DEFAULT_RUNNER_NAME); + verify(targetClient.customObjects(), times(6)).post(any(CustomObjectDraft.class)); + verifyLastSyncCustomObjectQuery( + targetClient, "stateSync", DEFAULT_RUNNER_NAME, "testProjectKey", 1); + verifyLastSyncCustomObjectQuery( + targetClient, "inventorySync", DEFAULT_RUNNER_NAME, "testProjectKey", 1); + verifyLastSyncCustomObjectQuery( + targetClient, "customObjectSync", DEFAULT_RUNNER_NAME, "testProjectKey", 1); + verify(sourceClientSpy, times(1)).states(); + verify(sourceClientSpy, times(1)).inventory(); + verify(sourceClientSpy, times(1)).customObjects(); + assertThat(verifyStatesGetCounter.get()).isEqualTo(1); + assertThat(verifyInventoryGetCounter.get()).isEqualTo(1); + assertThat(verifyCustomObjectsGetCounter.get()).isEqualTo(1); + verifyInteractionsWithClientAfterSync(sourceClientSpy, 3); + + assertStateSyncerLoggingEvents(stateSyncerTestLogger, 0); + assertInventoryEntrySyncerLoggingEvents(inventoryEntrySyncerTestLogger, 0); + assertCustomObjectSyncerLoggingEvents(customObjectSyncerTestLogger, 0); + } + + @Test + @SuppressWarnings("unchecked") + void syncTypesAndCategories_AsDelta_ShouldBuildSyncerAndExecuteSync() { + // preparation + final ProjectApiRoot sourceClientSpy = spy(sourceClient); + final ZonedDateTime currentCtpTimestamp = ZonedDateTime.now(); + final ProjectApiRoot targetClient = mock(ProjectApiRoot.class); + when(targetClient.getProjectKey()).thenReturn("testTargetProjectKey"); + stubClientsCustomObjectService(targetClient, currentCtpTimestamp); + + final SyncerFactory syncerFactory = + SyncerFactory.of(() -> sourceClientSpy, () -> targetClient, getMockedClock()); + + // test + String[] syncModuleOptions = {"types", "categories"}; + syncerFactory.sync(syncModuleOptions, null, false, false, null).join(); + + // assertions + verifyTimestampGeneratorCustomObjectUpsertIsCalled( + targetClient, "TypeSync", DEFAULT_RUNNER_NAME); + verifyTimestampGeneratorCustomObjectUpsertIsCalled( + targetClient, "CategorySync", DEFAULT_RUNNER_NAME); + verify(targetClient.customObjects(), times(4)).post(any(CustomObjectDraft.class)); + verifyLastSyncCustomObjectQuery( + targetClient, "typeSync", DEFAULT_RUNNER_NAME, "testProjectKey", 1); + verifyLastSyncCustomObjectQuery( + targetClient, "categorySync", DEFAULT_RUNNER_NAME, "testProjectKey", 1); + + final InOrder inOrder = Mockito.inOrder(sourceClientSpy); + + inOrder.verify(sourceClientSpy, times(1)).types(); + inOrder.verify(sourceClientSpy, times(1)).categories(); + assertThat(verifyTypesGetCounter.get()).isEqualTo(1); + assertThat(verifyCategoriesGetCounter.get()).isEqualTo(1); + verifyInteractionsWithClientAfterSync(sourceClientSpy, 2); + + assertTypeSyncerLoggingEvents(typeSyncerTestLogger, 0); + assertCategorySyncerLoggingEvents(categorySyncerTestLogger, 0); + assertThat(typeSyncerTestLogger.getAllLoggingEvents()).hasSize(2); + assertThat(categorySyncerTestLogger.getAllLoggingEvents()).hasSize(2); + } + + @Test + @SuppressWarnings("unchecked") + void syncProductsAndShoppingLists_AsDelta_ShouldBuildSyncerAndExecuteSync() { + // preparation + final ProjectApiRoot sourceSpy = spy(sourceClient); + final ZonedDateTime currentCtpTimestamp = ZonedDateTime.now(); + final ProjectApiRoot targetClient = mock(ProjectApiRoot.class); + when(targetClient.getProjectKey()).thenReturn("testTargetProjectKey"); + stubClientsCustomObjectService(targetClient, currentCtpTimestamp); + + final SyncerFactory syncerFactory = + SyncerFactory.of(() -> sourceSpy, () -> targetClient, getMockedClock()); + + // test + String[] syncModuleOptions = {"products", "shoppingLists"}; + syncerFactory.sync(syncModuleOptions, null, false, false, null).join(); + + // assertions + verifyTimestampGeneratorCustomObjectUpsertIsCalled( + targetClient, "ProductSync", DEFAULT_RUNNER_NAME); + verifyTimestampGeneratorCustomObjectUpsertIsCalled( + targetClient, "ShoppingListSync", DEFAULT_RUNNER_NAME); + verify(targetClient.customObjects(), times(4)).post(any(CustomObjectDraft.class)); + verifyLastSyncCustomObjectQuery( + targetClient, "productSync", DEFAULT_RUNNER_NAME, "testProjectKey", 1); + verifyLastSyncCustomObjectQuery( + targetClient, "shoppingListSync", DEFAULT_RUNNER_NAME, "testProjectKey", 1); + assertThat(verifyProductProjectionsGetCounter.get()).isEqualTo(1); + assertThat(verifyShoppingListsGetCounter.get()).isEqualTo(1); + verifyInteractionsWithClientAfterSync(sourceSpy, 2); + + assertProductSyncerLoggingEvents(productSyncerTestLogger, 0); + assertShoppingListSyncerLoggingEvents(shoppingListSyncerTestLogger, 0); + assertThat(productSyncerTestLogger.getAllLoggingEvents()).hasSize(2); + assertThat(shoppingListSyncerTestLogger.getAllLoggingEvents()).hasSize(2); + } + + @Test + void sync_AsDelta_WithOneUnmatchedSyncOptionValue_ShouldResultIllegalArgumentException() { + final SyncerFactory syncerFactory = + SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock()); + + // test + String[] syncResources = {"productTypes", "unknown", "shoppingLists"}; + CompletionStage result = syncerFactory.sync(syncResources, null, false, false, null); + + String errorMessage = + format( + "Unknown argument \"%s\" supplied to \"-s\" or \"--sync\" option! %s", + syncResources[1], SYNC_MODULE_OPTION_DESCRIPTION); + + assertThat(result) + .failsWithin(1, TimeUnit.SECONDS) + .withThrowableOfType(ExecutionException.class) + .withCauseExactlyInstanceOf(CliException.class) + .withMessageContaining(errorMessage); + } + + @Test + void sync_AsDelta_WithSyncOptionValuesAndAll_ShouldResultIllegalArgumentException() { + final SyncerFactory syncerFactory = + SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock()); + + // test + String[] syncResources = {"productTypes", "all", "shoppingLists"}; + CompletionStage result = syncerFactory.sync(syncResources, null, false, false, null); + + String errorMessage = + format( + "Wrong arguments supplied to \"-s\" or \"--sync\" option! " + + "'all' option cannot be passed along with other arguments.\" %s", + SYNC_MODULE_OPTION_DESCRIPTION); + + assertThat(result) + .failsWithin(1, TimeUnit.SECONDS) + .withThrowableOfType(ExecutionException.class) + .withCauseExactlyInstanceOf(CliException.class) + .withMessageContaining(errorMessage); + } + + private void verifyInteractionsWithClientAfterSync( + @Nonnull final ProjectApiRoot client, final int numberOfGetConfigInvocations) { + + verify(client, times(1)).close(); + // Verify config is accessed for the success message after sync: + // " example: Syncing products from CTP project with key 'x' to project with key 'y' is done"," + verify(client, times(numberOfGetConfigInvocations)).getProjectKey(); + } } diff --git a/src/test/java/com/commercetools/project/sync/util/TestUtils.java b/src/test/java/com/commercetools/project/sync/util/TestUtils.java index 937804c0..dacbbbed 100644 --- a/src/test/java/com/commercetools/project/sync/util/TestUtils.java +++ b/src/test/java/com/commercetools/project/sync/util/TestUtils.java @@ -1,5 +1,6 @@ package com.commercetools.project.sync.util; +import static io.vrap.rmf.base.client.utils.json.JsonUtils.fromInputStream; import static java.lang.String.format; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; @@ -10,7 +11,9 @@ import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; +import com.commercetools.api.client.ByProjectKeyCustomObjectsPost; import com.commercetools.api.client.ProjectApiRoot; +import com.commercetools.api.defaultconfig.ApiRootBuilder; import com.commercetools.api.models.custom_object.CustomObject; import com.commercetools.api.models.custom_object.CustomObjectDraft; import com.commercetools.api.models.error.ErrorResponse; @@ -23,15 +26,20 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectWriter; +import io.vrap.rmf.base.client.ApiHttpMethod; import io.vrap.rmf.base.client.ApiHttpResponse; import io.vrap.rmf.base.client.error.BadGatewayException; +import java.io.IOException; +import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.time.Clock; import java.time.ZonedDateTime; import java.util.Collections; import java.util.concurrent.CompletableFuture; import javax.annotation.Nonnull; +import org.apache.commons.lang3.StringUtils; import org.assertj.core.api.Condition; +import org.assertj.core.util.TriFunction; import uk.org.lidalia.slf4jext.Level; import uk.org.lidalia.slf4jtest.LoggingEvent; import uk.org.lidalia.slf4jtest.TestLogger; @@ -197,6 +205,22 @@ public static void verifyInteractionsWithClientAfterSync( verifyNoMoreInteractions(client); } + public static T readObjectFromResource(final String resourcePath, final Class objectType) { + final InputStream resourceAsStream = + Thread.currentThread().getContextClassLoader().getResourceAsStream(resourcePath); + return fromInputStream(resourceAsStream, objectType); + } + + public static String readStringFromFile(final String resourcePath) { + final InputStream resourceAsStream = + Thread.currentThread().getContextClassLoader().getResourceAsStream(resourcePath); + try { + return new String(resourceAsStream.readAllBytes(), StandardCharsets.UTF_8); + } catch (IOException e) { + return StringUtils.EMPTY; + } + } + @SuppressWarnings("unchecked") public static void stubClientsCustomObjectService( @Nonnull final ProjectApiRoot client, @Nonnull final ZonedDateTime currentCtpTimestamp) { @@ -204,12 +228,41 @@ public static void stubClientsCustomObjectService( final CustomObject customObject = mockLastSyncCustomObject(currentCtpTimestamp); final ApiHttpResponse apiHttpResponse = mock(ApiHttpResponse.class); when(apiHttpResponse.getBody()).thenReturn(customObject); - when(client.customObjects().post(any(CustomObjectDraft.class)).execute()) + final ByProjectKeyCustomObjectsPost customObjectsPost = + mock(ByProjectKeyCustomObjectsPost.class); + when(customObjectsPost.execute()) .thenReturn(CompletableFuture.completedFuture(apiHttpResponse)); + when(client.customObjects()).thenReturn(mock()); + when(client.customObjects().post(any(CustomObjectDraft.class))).thenReturn(customObjectsPost); + when(client.customObjects().withContainerAndKey(anyString(), anyString())).thenReturn(mock()); + when(client.customObjects().withContainerAndKey(anyString(), anyString()).get()) + .thenReturn(mock()); when(client.customObjects().withContainerAndKey(anyString(), anyString()).get().execute()) .thenReturn(CompletableFuture.completedFuture(apiHttpResponse)); } + public static ProjectApiRoot withTestClient( + final String projectKey, + TriFunction>> fn) { + return ApiRootBuilder.of( + request -> { + final String uri = request.getUri() != null ? request.getUri().toString() : ""; + final ApiHttpMethod method = request.getMethod(); + final String encodedRequestBody = + uri.contains("graphql") + ? new String(request.getBody(), StandardCharsets.UTF_8) + : ""; + final CompletableFuture> response = + fn.apply(uri, method, encodedRequestBody); + if (response != null) { + return response; + } + return null; + }) + .withApiBaseUrl("testBaseUri") + .build(projectKey); + } + @Nonnull @SuppressWarnings("unchecked") public static CustomObject mockLastSyncCustomObject(@Nonnull ZonedDateTime currentCtpTimestamp) { From 2e303ee8a315fc4f26df087f2413298ceb9a9e7a Mon Sep 17 00:00:00 2001 From: salander85 Date: Tue, 17 Oct 2023 17:21:48 +0200 Subject: [PATCH 05/14] Migrate unittests for CLIRunner --- .../project/sync/CliRunnerTest.java | 1789 ++++++++--------- 1 file changed, 796 insertions(+), 993 deletions(-) diff --git a/src/test/java/com/commercetools/project/sync/CliRunnerTest.java b/src/test/java/com/commercetools/project/sync/CliRunnerTest.java index 117556d9..020a7326 100644 --- a/src/test/java/com/commercetools/project/sync/CliRunnerTest.java +++ b/src/test/java/com/commercetools/project/sync/CliRunnerTest.java @@ -1,20 +1,64 @@ package com.commercetools.project.sync; +import static com.commercetools.project.sync.CliRunner.HELP_OPTION_DESCRIPTION; +import static com.commercetools.project.sync.CliRunner.HELP_OPTION_LONG; +import static com.commercetools.project.sync.CliRunner.HELP_OPTION_SHORT; +import static com.commercetools.project.sync.CliRunner.RUNNER_NAME_OPTION_DESCRIPTION; +import static com.commercetools.project.sync.CliRunner.RUNNER_NAME_OPTION_LONG; +import static com.commercetools.project.sync.CliRunner.RUNNER_NAME_OPTION_SHORT; +import static com.commercetools.project.sync.CliRunner.SYNC_MODULE_OPTION_DESCRIPTION; +import static com.commercetools.project.sync.CliRunner.SYNC_MODULE_OPTION_LONG; +import static com.commercetools.project.sync.CliRunner.SYNC_MODULE_OPTION_SHORT; +import static com.commercetools.project.sync.CliRunner.VERSION_OPTION_DESCRIPTION; +import static com.commercetools.project.sync.CliRunner.VERSION_OPTION_LONG; +import static com.commercetools.project.sync.CliRunner.VERSION_OPTION_SHORT; +import static com.commercetools.project.sync.util.SyncUtils.APPLICATION_DEFAULT_NAME; +import static com.commercetools.project.sync.util.SyncUtils.APPLICATION_DEFAULT_VERSION; +import static com.commercetools.project.sync.util.TestUtils.getMockedClock; +import static com.commercetools.project.sync.util.TestUtils.stubClientsCustomObjectService; +import static com.commercetools.project.sync.util.TestUtils.withTestClient; +import static java.lang.String.format; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.reset; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import com.commercetools.api.client.ByProjectKeyProductProjectionsGet; +import com.commercetools.api.client.ProjectApiRoot; +import com.commercetools.project.sync.exception.CliException; +import com.google.common.base.Optional; +import io.vrap.rmf.base.client.ApiHttpResponse; import java.io.ByteArrayOutputStream; import java.io.PrintStream; import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; +import java.time.ZonedDateTime; +import java.util.concurrent.CompletableFuture; import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.InOrder; +import org.mockito.Mockito; +import uk.org.lidalia.slf4jext.Level; import uk.org.lidalia.slf4jtest.TestLogger; import uk.org.lidalia.slf4jtest.TestLoggerFactory; -// These tests aren't migrated -// TODO: Migrate tests class CliRunnerTest { private static final TestLogger testLogger = TestLoggerFactory.getTestLogger(CliRunner.class); private static ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); private static PrintStream originalSystemOut; + private ProjectApiRoot sourceClient; + private ProjectApiRoot targetClient; @BeforeAll static void setupSuite() throws UnsupportedEncodingException { @@ -29,999 +73,758 @@ static void tearDownSuite() { } @BeforeEach + void setupTest() { + final ProjectApiRoot sourceClientWithEmtpyResults = + mockClientResourceGetRequestsWithEmptyResult("testProjectKey"); + sourceClient = spy(sourceClientWithEmtpyResults); + targetClient = mock(ProjectApiRoot.class); + when(targetClient.getProjectKey()).thenReturn("testTargetProjectKey"); + } + + @AfterEach void tearDownTest() { testLogger.clearAll(); + reset(sourceClient, targetClient); + } + + private ProjectApiRoot mockClientResourceGetRequestsWithEmptyResult(final String projectKey) { + return withTestClient( + projectKey, + (uri, method, encodedRequetsBody) -> { + final String responseString = "{\"results\":[]}"; + return CompletableFuture.completedFuture( + new ApiHttpResponse<>(200, null, responseString.getBytes(StandardCharsets.UTF_8))); + }); + } + + @Test + void run_WithEmptyArgumentList_ShouldFailAndLogError() { + // preparation + final SyncerFactory syncerFactory = + SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock()); + + // test + CliRunner.of().run(new String[] {}, syncerFactory); + + // assertion + assertThat(testLogger.getAllLoggingEvents()) + .hasSize(1) + .singleElement() + .satisfies( + loggingEvent -> { + assertThat(loggingEvent.getLevel()).isEqualTo(Level.ERROR); + assertThat(loggingEvent.getMessage()).contains("Failed to run sync process."); + final Optional actualThrowableOpt = loggingEvent.getThrowable(); + assertThat(actualThrowableOpt).isNotNull(); + assertThat(actualThrowableOpt.isPresent()).isTrue(); + final Throwable actualThrowable = actualThrowableOpt.get(); + assertThat(actualThrowable).isExactlyInstanceOf(CliException.class); + assertThat(actualThrowable.getMessage()) + .contains("Please pass at least 1 option to the CLI."); + }); + } + + @Test + void run_WithHelpAsLongArgument_ShouldPrintUsageHelpToStandardOut() + throws UnsupportedEncodingException { + // preparation + final SyncerFactory syncerFactory = + SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock()); + + // test + CliRunner.of().run(new String[] {"-help"}, syncerFactory); + + assertOutputStreamContainsHelpUsageWithSpecifiedCliOptions(); + } + + private void assertOutputStreamContainsHelpUsageWithSpecifiedCliOptions() + throws UnsupportedEncodingException { + assertThat(outputStream.toString("UTF-8")) + .contains(format("usage: %s", APPLICATION_DEFAULT_NAME)) + .contains(format("-%s,--%s", HELP_OPTION_SHORT, HELP_OPTION_LONG)) + .contains(format("-%s,--%s", SYNC_MODULE_OPTION_SHORT, SYNC_MODULE_OPTION_LONG)) + .contains(format("-%s,--%s", VERSION_OPTION_SHORT, VERSION_OPTION_LONG)); + } + + @Test + void run_WithHelpAsShortArgument_ShouldPrintUsageHelpToStandardOut() + throws UnsupportedEncodingException { + // preparation + final SyncerFactory syncerFactory = + SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock()); + + // test + CliRunner.of().run(new String[] {"-h"}, syncerFactory); + + assertOutputStreamContainsHelpUsageWithSpecifiedCliOptions(); + } + + @Test + void run_WithVersionAsShortArgument_ShouldPrintApplicationVersionToStandardOut() + throws UnsupportedEncodingException { + // preparation + final SyncerFactory syncerFactory = + SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock()); + + // test + CliRunner.of().run(new String[] {"-v"}, syncerFactory); + + assertThat(outputStream.toString("UTF-8")).contains(APPLICATION_DEFAULT_VERSION); + } + + @Test + void run_WithVersionAsLongArgument_ShouldPrintApplicationVersionToStandardOut() + throws UnsupportedEncodingException { + // preparation + final SyncerFactory syncerFactory = + SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock()); + + // test + CliRunner.of().run(new String[] {"--version"}, syncerFactory); + + assertThat(outputStream.toString("UTF-8")).contains(APPLICATION_DEFAULT_VERSION); } - // @Test - // void run_WithEmptyArgumentList_ShouldFailAndLogError() { - // // preparation - // final SyncerFactory syncerFactory = - // SyncerFactory.of( - // () -> mock(SphereClient.class), () -> mock(SphereClient.class), getMockedClock()); - // - // // test - // CliRunner.of().run(new String[] {}, syncerFactory); - // - // // assertion - // assertThat(testLogger.getAllLoggingEvents()) - // .hasSize(1) - // .singleElement() - // .satisfies( - // loggingEvent -> { - // assertThat(loggingEvent.getLevel()).isEqualTo(Level.ERROR); - // assertThat(loggingEvent.getMessage()).contains("Failed to run sync process."); - // final Optional actualThrowableOpt = loggingEvent.getThrowable(); - // assertThat(actualThrowableOpt).isNotNull(); - // assertThat(actualThrowableOpt.isPresent()).isTrue(); - // final Throwable actualThrowable = actualThrowableOpt.get(); - // assertThat(actualThrowable).isExactlyInstanceOf(CliException.class); - // assertThat(actualThrowable.getMessage()) - // .contains("Please pass at least 1 option to the CLI."); - // }); - // } - // - // @Test - // void run_WithHelpAsLongArgument_ShouldPrintUsageHelpToStandardOut() - // throws UnsupportedEncodingException { - // // preparation - // final SyncerFactory syncerFactory = - // SyncerFactory.of( - // () -> mock(SphereClient.class), () -> mock(SphereClient.class), getMockedClock()); - // - // // test - // CliRunner.of().run(new String[] {"-help"}, syncerFactory); - // - // assertOutputStreamContainsHelpUsageWithSpecifiedCliOptions(); - // } - // - // private void assertOutputStreamContainsHelpUsageWithSpecifiedCliOptions() - // throws UnsupportedEncodingException { - // assertThat(outputStream.toString("UTF-8")) - // .contains(format("usage: %s", APPLICATION_DEFAULT_NAME)) - // .contains(format("-%s,--%s", HELP_OPTION_SHORT, HELP_OPTION_LONG)) - // .contains(format("-%s,--%s", SYNC_MODULE_OPTION_SHORT, SYNC_MODULE_OPTION_LONG)) - // .contains(format("-%s,--%s", VERSION_OPTION_SHORT, VERSION_OPTION_LONG)); - // } - // - // @Test - // void run_WithHelpAsShortArgument_ShouldPrintUsageHelpToStandardOut() - // throws UnsupportedEncodingException { - // // preparation - // final SyncerFactory syncerFactory = - // SyncerFactory.of( - // () -> mock(SphereClient.class), () -> mock(SphereClient.class), getMockedClock()); - // - // // test - // CliRunner.of().run(new String[] {"-h"}, syncerFactory); - // - // assertOutputStreamContainsHelpUsageWithSpecifiedCliOptions(); - // } - // - // @Test - // void run_WithVersionAsShortArgument_ShouldPrintApplicationVersionToStandardOut() - // throws UnsupportedEncodingException { - // // preparation - // final SyncerFactory syncerFactory = - // SyncerFactory.of( - // () -> mock(SphereClient.class), () -> mock(SphereClient.class), getMockedClock()); - // - // // test - // CliRunner.of().run(new String[] {"-v"}, syncerFactory); - // - // assertThat(outputStream.toString("UTF-8")).contains(APPLICATION_DEFAULT_VERSION); - // } - // - // @Test - // void run_WithVersionAsLongArgument_ShouldPrintApplicationVersionToStandardOut() - // throws UnsupportedEncodingException { - // // preparation - // final SyncerFactory syncerFactory = - // SyncerFactory.of( - // () -> mock(SphereClient.class), () -> mock(SphereClient.class), getMockedClock()); - // - // // test - // CliRunner.of().run(new String[] {"--version"}, syncerFactory); - // - // assertThat(outputStream.toString("UTF-8")).contains(APPLICATION_DEFAULT_VERSION); - // } - // - // @Test - // void run_WithSyncAsArgumentWithNoArgs_ShouldFailAndLogError() { - // // preparation - // final SyncerFactory syncerFactory = - // SyncerFactory.of( - // () -> mock(SphereClient.class), () -> mock(SphereClient.class), getMockedClock()); - // - // // test - // CliRunner.of().run(new String[] {"-s"}, syncerFactory); - // - // // assertion - // assertThat(testLogger.getAllLoggingEvents()) - // .hasSize(1) - // .singleElement() - // .satisfies( - // loggingEvent -> { - // assertThat(loggingEvent.getLevel()).isEqualTo(Level.ERROR); - // assertThat(loggingEvent.getMessage()).contains("Failed to run sync process."); - // final Optional actualThrowableOpt = loggingEvent.getThrowable(); - // assertThat(actualThrowableOpt).isNotNull(); - // assertThat(actualThrowableOpt.isPresent()).isTrue(); - // final Throwable actualThrowable = actualThrowableOpt.get(); - // assertThat(actualThrowable).isExactlyInstanceOf(CliException.class); - // assertThat(actualThrowable.getMessage()).contains("Missing argument for option: - // s"); - // }); - // } - // - // @Test - // void run_WithFullSyncAsFirstArgument_ShouldFailAndLogError() { - // // preparation - // final SyncerFactory syncerFactory = - // SyncerFactory.of( - // () -> mock(SphereClient.class), () -> mock(SphereClient.class), getMockedClock()); - // - // // test - // CliRunner.of().run(new String[] {"-f"}, syncerFactory); - // - // // assertion - // assertThat(testLogger.getAllLoggingEvents()) - // .hasSize(1) - // .singleElement() - // .satisfies( - // loggingEvent -> { - // assertThat(loggingEvent.getLevel()).isEqualTo(Level.ERROR); - // assertThat(loggingEvent.getMessage()).contains("Failed to run sync process."); - // final Optional actualThrowableOpt = loggingEvent.getThrowable(); - // assertThat(actualThrowableOpt).isNotNull(); - // assertThat(actualThrowableOpt.isPresent()).isTrue(); - // final Throwable actualThrowable = actualThrowableOpt.get(); - // assertThat(actualThrowable).isExactlyInstanceOf(CliException.class); - // assertThat(actualThrowable.getMessage()) - // .contains("Please check that the first sync option is either -s, -h or -v."); - // }); - // } - // - // @Test - // void run_AsProductDeltaSync_ShouldBuildSyncerAndExecuteSync() { - // // preparation - // final SphereClient sourceClient = mock(SphereClient.class); - // when(sourceClient.getConfig()).thenReturn(SphereClientConfig.of("foo", "foo", "foo")); - // - // final SphereClient targetClient = mock(SphereClient.class); - // when(targetClient.getConfig()).thenReturn(SphereClientConfig.of("bar", "bar", "bar")); - // - // when(sourceClient.execute(any(ProductProjectionQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // - // final SyncerFactory syncerFactory = - // spy(SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock())); - // - // stubClientsCustomObjectService(targetClient, ZonedDateTime.now()); - // - // // test - // CliRunner.of().run(new String[] {"-s", "products"}, syncerFactory); - // - // // assertions - // verify(syncerFactory, times(1)).sync(new String[] {"products"}, null, false, false, null); - // verify(sourceClient, times(1)).execute(any(ProductProjectionQuery.class)); - // } - // - // @Test - // void run_AsProductFullSync_ShouldBuildSyncerAndExecuteSync() { - // // preparation - // final SphereClient sourceClient = mock(SphereClient.class); - // when(sourceClient.getConfig()).thenReturn(SphereClientConfig.of("foo", "foo", "foo")); - // - // final SphereClient targetClient = mock(SphereClient.class); - // when(targetClient.getConfig()).thenReturn(SphereClientConfig.of("bar", "bar", "bar")); - // - // when(sourceClient.execute(any(ProductProjectionQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // - // final SyncerFactory syncerFactory = - // spy(SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock())); - // - // stubClientsCustomObjectService(targetClient, ZonedDateTime.now()); - // - // // test - // CliRunner.of().run(new String[] {"-s", "products", "-f"}, syncerFactory); - // - // // assertions - // verify(syncerFactory, times(1)).sync(new String[] {"products"}, null, true, false, null); - // verify(sourceClient, times(1)).execute(any(ProductProjectionQuery.class)); - // } - // - // @Test - // void - // - // run_AsProductSyncWithCustomProductQueriesAndLimit_ShouldBuildSyncerAndExecuteQuerySuccessfully() { - // // preparation - // final SphereClient sourceClient = mock(SphereClient.class); - // when(sourceClient.getConfig()).thenReturn(SphereClientConfig.of("foo", "foo", "foo")); - // - // final SphereClient targetClient = mock(SphereClient.class); - // when(targetClient.getConfig()).thenReturn(SphereClientConfig.of("bar", "bar", "bar")); - // - // when(sourceClient.execute(any(ProductProjectionQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // - // final Long limit = 100L; - // final String customQuery = - // "\"published=true AND masterData(masterVariant(attributes(name= \\\"abc\\\" AND - // value=123)))\""; - // final String productQueryParametersValue = - // "{\"limit\": " + limit + ", \"where\": " + customQuery + "}"; - // - // final SyncerFactory syncerFactory = - // spy(SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock())); - // - // stubClientsCustomObjectService(targetClient, ZonedDateTime.now()); - // // test - // CliRunner.of() - // .run( - // new String[] { - // "-s", "products", "-f", "-productQueryParameters", productQueryParametersValue - // }, - // syncerFactory); - // - // // assertions - // verify(sourceClient, times(1)).execute(any(ProductProjectionQuery.class)); - // } - // - // @Test - // void - // - // run_AsProductSyncWithProductQueryParametersAndOnlyLimit_ShouldBuildSyncerAndExecuteQuerySuccessfully() { - // // preparation - // final SphereClient sourceClient = mock(SphereClient.class); - // when(sourceClient.getConfig()).thenReturn(SphereClientConfig.of("foo", "foo", "foo")); - // - // final SphereClient targetClient = mock(SphereClient.class); - // when(targetClient.getConfig()).thenReturn(SphereClientConfig.of("bar", "bar", "bar")); - // - // when(sourceClient.execute(any(ProductProjectionQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // - // final Long limit = 100L; - // final String productQueryParametersValue = "{\"limit\": " + limit + "}"; - // - // final SyncerFactory syncerFactory = - // spy(SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock())); - // - // stubClientsCustomObjectService(targetClient, ZonedDateTime.now()); - // // test - // CliRunner.of() - // .run( - // new String[] { - // "-s", "products", "-f", "-productQueryParameters", productQueryParametersValue - // }, - // syncerFactory); - // - // // assertions - // verify(sourceClient, times(1)).execute(any(ProductProjectionQuery.class)); - // } - // - // @Test - // void - // - // run_AsProductSyncWithProductQueryParametersAndOnlyWhere_ShouldBuildSyncerAndExecuteQuerySuccessfully() { - // // preparation - // final SphereClient sourceClient = mock(SphereClient.class); - // when(sourceClient.getConfig()).thenReturn(SphereClientConfig.of("foo", "foo", "foo")); - // - // final SphereClient targetClient = mock(SphereClient.class); - // when(targetClient.getConfig()).thenReturn(SphereClientConfig.of("bar", "bar", "bar")); - // - // when(sourceClient.execute(any(ProductProjectionQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // - // final String customQuery = - // "\"published=true AND masterVariant(attributes(name= \\\"abc\\\" AND value=123))\""; - // final String productQueryParametersValue = "{\"where\": " + customQuery + "}"; - // - // final SyncerFactory syncerFactory = - // spy(SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock())); - // - // stubClientsCustomObjectService(targetClient, ZonedDateTime.now()); - // // test - // CliRunner.of() - // .run( - // new String[] { - // "-s", "products", "-f", "-productQueryParameters", productQueryParametersValue - // }, - // syncerFactory); - // - // // assertions - // verify(sourceClient, times(1)).execute(any(ProductProjectionQuery.class)); - // } - // - // @Test - // void run_WithWrongFormatProductQueryParametersArgument_ShouldThrowCLIException() { - // // preparation - // final SphereClient sourceClient = mock(SphereClient.class); - // when(sourceClient.getConfig()).thenReturn(SphereClientConfig.of("foo", "foo", "foo")); - // - // final SphereClient targetClient = mock(SphereClient.class); - // when(targetClient.getConfig()).thenReturn(SphereClientConfig.of("bar", "bar", "bar")); - // - // final Long limit = 100L; - // final String customQuery = - // "\"published=true AND masterVariant(attributes(name= \"abc\\\" AND value=123))\""; - // final String productQueryParametersValue = - // "{\"limit\": " + limit + ", \"where\": " + customQuery + "}"; - // - // final SyncerFactory syncerFactory = - // spy(SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock())); - // - // // test - // CliRunner.of() - // .run( - // new String[] { - // "-s", "products", "-f", "-productQueryParameters", productQueryParametersValue - // }, - // syncerFactory); - // - // // assertion - // assertThat(testLogger.getAllLoggingEvents()) - // .hasSize(1) - // .singleElement() - // .satisfies( - // loggingEvent -> { - // assertThat(loggingEvent.getLevel()).isEqualTo(Level.ERROR); - // assertThat(loggingEvent.getMessage()).contains("Failed to run sync process."); - // final Optional actualThrowableOpt = loggingEvent.getThrowable(); - // assertThat(actualThrowableOpt).isNotNull(); - // assertThat(actualThrowableOpt.isPresent()).isTrue(); - // final Throwable actualThrowable = actualThrowableOpt.get(); - // assertThat(actualThrowable).isExactlyInstanceOf(CliException.class); - // }); - // } - // - // @Test - // void run_WithInvalidLimitInProductQueryParametersArgument_ShouldThrowCLIException() { - // // preparation - // final SphereClient sourceClient = mock(SphereClient.class); - // when(sourceClient.getConfig()).thenReturn(SphereClientConfig.of("foo", "foo", "foo")); - // - // final SphereClient targetClient = mock(SphereClient.class); - // when(targetClient.getConfig()).thenReturn(SphereClientConfig.of("bar", "bar", "bar")); - // - // final Long limit = -100L; - // final String customQuery = - // "\"published=true AND masterVariant(attributes(name= \"abc\\\" AND value=123))\""; - // final String productQueryParametersValue = - // "{\"limit\": " + limit + ", \"where\": " + customQuery + "}"; - // - // final SyncerFactory syncerFactory = - // spy(SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock())); - // - // // test - // CliRunner.of() - // .run( - // new String[] { - // "-s", "products", "-f", "-productQueryParameters", productQueryParametersValue - // }, - // syncerFactory); - // - // // assertion - // assertThat(testLogger.getAllLoggingEvents()) - // .hasSize(1) - // .singleElement() - // .satisfies( - // loggingEvent -> { - // assertThat(loggingEvent.getLevel()).isEqualTo(Level.ERROR); - // assertThat(loggingEvent.getMessage()).contains("Failed to run sync process."); - // final Optional actualThrowableOpt = loggingEvent.getThrowable(); - // assertThat(actualThrowableOpt).isNotNull(); - // assertThat(actualThrowableOpt.isPresent()).isTrue(); - // final Throwable actualThrowable = actualThrowableOpt.get(); - // assertThat(actualThrowable).isExactlyInstanceOf(CliException.class); - // assertThat(actualThrowable.getMessage()) - // .contains("limit -100 cannot be less than 1."); - // }); - // } - // - // @Test - // void run_AsTaxCategoryDeltaSync_ShouldBuildSyncerAndExecuteSync() { - // // preparation - // final SphereClient sourceClient = mock(SphereClient.class); - // when(sourceClient.getConfig()).thenReturn(SphereClientConfig.of("foo", "foo", "foo")); - // - // final SphereClient targetClient = mock(SphereClient.class); - // when(targetClient.getConfig()).thenReturn(SphereClientConfig.of("bar", "bar", "bar")); - // - // when(sourceClient.execute(any(ProductProjectionQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // - // final SyncerFactory syncerFactory = - // spy(SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock())); - // - // stubClientsCustomObjectService(targetClient, ZonedDateTime.now()); - // - // // test - // CliRunner.of().run(new String[] {"-s", "taxCategories"}, syncerFactory); - // - // // assertions - // verify(syncerFactory, times(1)).sync(new String[] {"taxCategories"}, null, false, false, - // null); - // verify(sourceClient, times(1)).execute(any(TaxCategoryQuery.class)); - // } - // - // @Test - // void run_AsTaxCategoryFullSync_ShouldBuildSyncerAndExecuteSync() { - // // preparation - // final SphereClient sourceClient = mock(SphereClient.class); - // when(sourceClient.getConfig()).thenReturn(SphereClientConfig.of("foo", "foo", "foo")); - // - // final SphereClient targetClient = mock(SphereClient.class); - // when(targetClient.getConfig()).thenReturn(SphereClientConfig.of("bar", "bar", "bar")); - // - // when(sourceClient.execute(any(TaxCategoryQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // - // final SyncerFactory syncerFactory = - // spy(SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock())); - // - // stubClientsCustomObjectService(targetClient, ZonedDateTime.now()); - // - // // test - // CliRunner.of().run(new String[] {"-s", "taxCategories", "-f"}, syncerFactory); - // - // // assertions - // verify(syncerFactory, times(1)).sync(new String[] {"taxCategories"}, null, true, false, - // null); - // verify(sourceClient, times(1)).execute(any(TaxCategoryQuery.class)); - // } - // - // @Test - // void run_AsCustomerDeltaSync_ShouldBuildSyncerAndExecuteSync() { - // // preparation - // final SphereClient sourceClient = mock(SphereClient.class); - // when(sourceClient.getConfig()).thenReturn(SphereClientConfig.of("foo", "foo", "foo")); - // - // final SphereClient targetClient = mock(SphereClient.class); - // when(targetClient.getConfig()).thenReturn(SphereClientConfig.of("bar", "bar", "bar")); - // - // final SyncerFactory syncerFactory = - // spy(SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock())); - // - // stubClientsCustomObjectService(targetClient, ZonedDateTime.now()); - // - // // test - // CliRunner.of().run(new String[] {"-s", "customers"}, syncerFactory); - // - // // assertions - // verify(syncerFactory, times(1)).sync(new String[] {"customers"}, null, false, false, null); - // verify(sourceClient, times(1)).execute(any(CustomerQuery.class)); - // } - // - // @Test - // void run_AsCustomerFullSync_ShouldBuildSyncerAndExecuteSync() { - // // preparation - // final SphereClient sourceClient = mock(SphereClient.class); - // when(sourceClient.getConfig()).thenReturn(SphereClientConfig.of("foo", "foo", "foo")); - // - // final SphereClient targetClient = mock(SphereClient.class); - // when(targetClient.getConfig()).thenReturn(SphereClientConfig.of("bar", "bar", "bar")); - // - // when(sourceClient.execute(any(CustomerQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // - // final SyncerFactory syncerFactory = - // spy(SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock())); - // - // stubClientsCustomObjectService(targetClient, ZonedDateTime.now()); - // - // // test - // CliRunner.of().run(new String[] {"-s", "customers", "-f"}, syncerFactory); - // - // // assertions - // verify(syncerFactory, times(1)).sync(new String[] {"customers"}, null, true, false, null); - // verify(sourceClient, times(1)).execute(any(CustomerQuery.class)); - // } - // - // @Test - // void run_AsShoppingListDeltaSync_ShouldBuildSyncerAndExecuteSync() { - // // preparation - // final SphereClient sourceClient = mock(SphereClient.class); - // when(sourceClient.getConfig()).thenReturn(SphereClientConfig.of("foo", "foo", "foo")); - // - // final SphereClient targetClient = mock(SphereClient.class); - // when(targetClient.getConfig()).thenReturn(SphereClientConfig.of("bar", "bar", "bar")); - // - // final SyncerFactory syncerFactory = - // spy(SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock())); - // - // stubClientsCustomObjectService(targetClient, ZonedDateTime.now()); - // - // // test - // CliRunner.of().run(new String[] {"-s", "shoppingLists"}, syncerFactory); - // - // // assertions - // verify(syncerFactory, times(1)).sync(new String[] {"shoppingLists"}, null, false, false, - // null); - // verify(sourceClient, times(1)).execute(any(ShoppingListQuery.class)); - // } - // - // @Test - // void run_AsShoppingListFullSync_ShouldBuildSyncerAndExecuteSync() { - // // preparation - // final SphereClient sourceClient = mock(SphereClient.class); - // when(sourceClient.getConfig()).thenReturn(SphereClientConfig.of("foo", "foo", "foo")); - // - // final SphereClient targetClient = mock(SphereClient.class); - // when(targetClient.getConfig()).thenReturn(SphereClientConfig.of("bar", "bar", "bar")); - // - // when(sourceClient.execute(any(ShoppingListQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // - // final SyncerFactory syncerFactory = - // spy(SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock())); - // - // stubClientsCustomObjectService(targetClient, ZonedDateTime.now()); - // - // // test - // CliRunner.of().run(new String[] {"-s", "shoppingLists", "-f"}, syncerFactory); - // - // // assertions - // verify(syncerFactory, times(1)).sync(new String[] {"shoppingLists"}, null, true, false, - // null); - // verify(sourceClient, times(1)).execute(any(ShoppingListQuery.class)); - // } - // - // @Test - // void run_AsCustomObjectDeltaSync_ShouldBuildSyncerAndExecuteSync() { - // // preparation - // final SphereClient sourceClient = mock(SphereClient.class); - // when(sourceClient.getConfig()).thenReturn(SphereClientConfig.of("foo", "foo", "foo")); - // - // final SphereClient targetClient = mock(SphereClient.class); - // when(targetClient.getConfig()).thenReturn(SphereClientConfig.of("bar", "bar", "bar")); - // - // when(sourceClient.execute(any(CustomObjectQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // - // final SyncerFactory syncerFactory = - // spy(SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock())); - // - // stubClientsCustomObjectService(targetClient, ZonedDateTime.now()); - // - // // test - // CliRunner.of().run(new String[] {"-s", "customObjects"}, syncerFactory); - // - // // assertions - // verify(syncerFactory, times(1)).sync(new String[] {"customObjects"}, null, false, false, - // null); - // verify(sourceClient, times(1)).execute(any(CustomObjectQuery.class)); - // } - // - // @Test - // void run_AsCustomObjectFullSync_ShouldBuildSyncerAndExecuteSync() { - // // preparation - // final SphereClient sourceClient = mock(SphereClient.class); - // when(sourceClient.getConfig()).thenReturn(SphereClientConfig.of("foo", "foo", "foo")); - // - // final SphereClient targetClient = mock(SphereClient.class); - // when(targetClient.getConfig()).thenReturn(SphereClientConfig.of("bar", "bar", "bar")); - // - // when(sourceClient.execute(any(CustomObjectQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // - // final SyncerFactory syncerFactory = - // spy(SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock())); - // - // stubClientsCustomObjectService(targetClient, ZonedDateTime.now()); - // - // // test - // CliRunner.of().run(new String[] {"-s", "customObjects", "-f"}, syncerFactory); - // - // // assertions - // verify(syncerFactory, times(1)).sync(new String[] {"customObjects"}, null, true, false, - // null); - // verify(sourceClient, times(1)).execute(any(CustomObjectQuery.class)); - // } - // - // @Test - // void run_AsCartDiscountFullSync_ShouldBuildSyncerAndExecuteSync() { - // // preparation - // final SphereClient sourceClient = mock(SphereClient.class); - // when(sourceClient.getConfig()).thenReturn(SphereClientConfig.of("foo", "foo", "foo")); - // - // final SphereClient targetClient = mock(SphereClient.class); - // when(targetClient.getConfig()).thenReturn(SphereClientConfig.of("bar", "bar", "bar")); - // - // when(sourceClient.execute(any(CartDiscountQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // - // final SyncerFactory syncerFactory = - // spy(SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock())); - // - // stubClientsCustomObjectService(targetClient, ZonedDateTime.now()); - // - // // test - // CliRunner.of().run(new String[] {"-s", "cartDiscounts", "-f"}, syncerFactory); - // - // // assertions - // verify(syncerFactory, times(1)).sync(new String[] {"cartDiscounts"}, null, true, false, - // null); - // verify(sourceClient, times(1)).execute(any(CartDiscountQuery.class)); - // } - // - // @Test - // void run_AsStateFullSync_ShouldBuildSyncerAndExecuteSync() { - // // preparation - // final SphereClient sourceClient = mock(SphereClient.class); - // when(sourceClient.getConfig()).thenReturn(SphereClientConfig.of("foo", "foo", "foo")); - // - // final SphereClient targetClient = mock(SphereClient.class); - // when(targetClient.getConfig()).thenReturn(SphereClientConfig.of("bar", "bar", "bar")); - // - // when(sourceClient.execute(any(StateQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // - // final SyncerFactory syncerFactory = - // spy(SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock())); - // - // stubClientsCustomObjectService(targetClient, ZonedDateTime.now()); - // - // // test - // CliRunner.of().run(new String[] {"-s", "states", "-f"}, syncerFactory); - // - // // assertions - // verify(syncerFactory, times(1)).sync(new String[] {"states"}, null, true, false, null); - // verify(sourceClient, times(1)).execute(any(StateQuery.class)); - // } - // - // @Test - // void run_WithSyncAsLongArgument_ShouldBuildSyncerAndExecuteSync() { - // // preparation - // final SphereClient sourceClient = mock(SphereClient.class); - // when(sourceClient.getConfig()).thenReturn(SphereClientConfig.of("foo", "foo", "foo")); - // - // final SphereClient targetClient = mock(SphereClient.class); - // when(targetClient.getConfig()).thenReturn(SphereClientConfig.of("bar", "bar", "bar")); - // - // when(sourceClient.execute(any(ProductProjectionQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // - // final SyncerFactory syncerFactory = - // spy(SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock())); - // - // stubClientsCustomObjectService(targetClient, ZonedDateTime.now()); - // - // // test - // CliRunner.of().run(new String[] {"--sync", "products"}, syncerFactory); - // - // // assertions - // verify(syncerFactory, times(1)).sync(new String[] {"products"}, null, false, false, null); - // verify(sourceClient, times(1)).execute(any(ProductProjectionQuery.class)); - // } - // - // @Test - // void run_WithRunnerName_ShouldProcessSyncOption() { - // // preparation - // final SphereClient sourceClient = mock(SphereClient.class); - // when(sourceClient.getConfig()).thenReturn(SphereClientConfig.of("foo", "foo", "foo")); - // - // final SphereClient targetClient = mock(SphereClient.class); - // when(targetClient.getConfig()).thenReturn(SphereClientConfig.of("bar", "bar", "bar")); - // - // when(sourceClient.execute(any(ProductProjectionQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // - // final SyncerFactory syncerFactory = - // spy(SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock())); - // - // stubClientsCustomObjectService(targetClient, ZonedDateTime.now()); - // - // // test - // CliRunner.of().run(new String[] {"--sync", "products", "-r", "Runner123"}, syncerFactory); - // - // // assertions - // verify(syncerFactory, times(1)) - // .sync(new String[] {"products"}, "Runner123", false, false, null); - // verify(sourceClient, times(1)).execute(any(ProductProjectionQuery.class)); - // } - // - // @Test - // void run_WithRunnerNameLong_ShouldProcessSyncOption() { - // // preparation - // final SphereClient sourceClient = mock(SphereClient.class); - // when(sourceClient.getConfig()).thenReturn(SphereClientConfig.of("foo", "foo", "foo")); - // - // final SphereClient targetClient = mock(SphereClient.class); - // when(targetClient.getConfig()).thenReturn(SphereClientConfig.of("bar", "bar", "bar")); - // - // when(sourceClient.execute(any(ProductProjectionQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // - // final SyncerFactory syncerFactory = - // spy(SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock())); - // - // stubClientsCustomObjectService(targetClient, ZonedDateTime.now()); - // - // // test - // CliRunner.of() - // .run( - // new String[] {"--sync", "products", "--runnerName", "Runner123", "--full"}, - // syncerFactory); - // - // // assertions - // verify(syncerFactory, times(1)).sync(new String[] {"products"}, "Runner123", true, false, - // null); - // verify(sourceClient, times(1)).execute(any(ProductProjectionQuery.class)); - // } - // - // @Test - // void run_WithUnknownArgument_ShouldPrintAndLogError() { - // // preparation - // final SyncerFactory syncerFactory = - // spy( - // SyncerFactory.of( - // () -> mock(SphereClient.class), () -> mock(SphereClient.class), - // getMockedClock())); - // // test - // CliRunner.of().run(new String[] {"-u"}, syncerFactory); - // - // // Assert error log - // verify(syncerFactory, never()).sync(any(), any(), anyBoolean(), anyBoolean(), any()); - // } - // - // @Test - // void run_WithHelpAsArgument_ShouldPrintThreeOptionsWithDescriptionsToSystemOut() - // throws UnsupportedEncodingException { - // // preparation - // final SyncerFactory syncerFactory = - // spy( - // SyncerFactory.of( - // () -> mock(SphereClient.class), () -> mock(SphereClient.class), - // getMockedClock())); - // - // // test - // CliRunner.of().run(new String[] {"-h"}, syncerFactory); - // - // // assertions - // assertThat(testLogger.getAllLoggingEvents()).isEmpty(); - // - // // Remove line breaks from output stream string. - // final String outputStreamWithoutLineBreaks = outputStream.toString("UTF-8").replace("\n", - // ""); - // - // // Replace multiple spaces with single space in output stream string. - // final String outputStreamWithSingleSpaces = - // outputStreamWithoutLineBreaks.trim().replaceAll(" +", " "); - // - // assertThat(outputStreamWithSingleSpaces) - // .contains( - // format("-%s,--%s %s", HELP_OPTION_SHORT, HELP_OPTION_LONG, HELP_OPTION_DESCRIPTION)) - // .contains( - // format( - // "-%s,--%s %s", - // SYNC_MODULE_OPTION_SHORT, SYNC_MODULE_OPTION_LONG, - // SYNC_MODULE_OPTION_DESCRIPTION)) - // .contains( - // format( - // "-%s,--%s %s", - // RUNNER_NAME_OPTION_SHORT, RUNNER_NAME_OPTION_LONG, - // RUNNER_NAME_OPTION_DESCRIPTION)) - // .contains( - // format( - // "-%s,--%s %s", - // VERSION_OPTION_SHORT, VERSION_OPTION_LONG, VERSION_OPTION_DESCRIPTION)); - // verify(syncerFactory, never()).sync(any(), any(), anyBoolean(), anyBoolean(), any()); - // } - // - // @Test - // void run_WithSyncAsArgumentWithAllArg_ShouldExecuteAllSyncers() { - // // preparation - // final SphereClient sourceClient = mock(SphereClient.class); - // when(sourceClient.getConfig()).thenReturn(SphereClientConfig.of("foo", "foo", "foo")); - // - // final SphereClient targetClient = mock(SphereClient.class); - // when(targetClient.getConfig()).thenReturn(SphereClientConfig.of("bar", "bar", "bar")); - // - // when(sourceClient.execute(any(ProductTypeQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // when(sourceClient.execute(any(TypeQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // when(sourceClient.execute(any(CategoryQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // when(sourceClient.execute(any(InventoryEntryQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // when(sourceClient.execute(any(ProductProjectionQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // when(sourceClient.execute(any(CartDiscountQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // when(sourceClient.execute(any(StateQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // when(sourceClient.execute(any(TaxCategoryQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // when(sourceClient.execute(any(CustomObjectQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // when(sourceClient.execute(any(CustomerQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // when(sourceClient.execute(any(ShoppingListQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // - // stubClientsCustomObjectService(targetClient, ZonedDateTime.now()); - // - // final SyncerFactory syncerFactory = - // spy(SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock())); - // - // // test - // CliRunner.of().run(new String[] {"-s", "all"}, syncerFactory); - // - // // assertions - // verify(syncerFactory, times(1)).sync(new String[] {"all"}, null, false, false, null); - // verify(sourceClient, times(1)).execute(any(ProductTypeQuery.class)); - // verify(sourceClient, times(1)).execute(any(TypeQuery.class)); - // verify(sourceClient, times(1)).execute(any(TaxCategoryQuery.class)); - // verify(sourceClient, times(1)).execute(any(CategoryQuery.class)); - // verify(sourceClient, times(1)).execute(any(ProductProjectionQuery.class)); - // verify(sourceClient, times(1)).execute(any(InventoryEntryQuery.class)); - // verify(sourceClient, times(1)).execute(any(CartDiscountQuery.class)); - // verify(sourceClient, times(1)).execute(any(StateQuery.class)); - // verify(sourceClient, times(1)).execute(any(CustomObjectQuery.class)); - // verify(sourceClient, times(1)).execute(any(CustomerQuery.class)); - // verify(sourceClient, times(1)).execute(any(ShoppingListQuery.class)); - // } - // - // @Test - // void run_WithSyncAsArgumentWithAllArgWithRunnerName_ShouldExecuteAllSyncers() { - // // preparation - // final SphereClient sourceClient = mock(SphereClient.class); - // when(sourceClient.getConfig()).thenReturn(SphereClientConfig.of("foo", "foo", "foo")); - // - // final SphereClient targetClient = mock(SphereClient.class); - // when(targetClient.getConfig()).thenReturn(SphereClientConfig.of("bar", "bar", "bar")); - // - // when(sourceClient.execute(any(ProductTypeQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // when(sourceClient.execute(any(TypeQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // when(sourceClient.execute(any(CategoryQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // when(sourceClient.execute(any(InventoryEntryQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // when(sourceClient.execute(any(ProductProjectionQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // when(sourceClient.execute(any(CartDiscountQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // when(sourceClient.execute(any(StateQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // when(sourceClient.execute(any(TaxCategoryQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // when(sourceClient.execute(any(CustomObjectQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // when(sourceClient.execute(any(CustomerQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // when(sourceClient.execute(any(ShoppingListQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // - // stubClientsCustomObjectService(targetClient, ZonedDateTime.now()); - // - // final SyncerFactory syncerFactory = - // spy(SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock())); - // - // // test - // CliRunner.of().run(new String[] {"-s", "all", "-r", "myRunner"}, syncerFactory); - // - // // assertions - // verify(syncerFactory, times(1)).sync(new String[] {"all"}, "myRunner", false, false, null); - // verify(sourceClient, times(1)).execute(any(ProductTypeQuery.class)); - // verify(sourceClient, times(1)).execute(any(TypeQuery.class)); - // verify(sourceClient, times(1)).execute(any(TaxCategoryQuery.class)); - // verify(sourceClient, times(1)).execute(any(CategoryQuery.class)); - // verify(sourceClient, times(1)).execute(any(ProductProjectionQuery.class)); - // verify(sourceClient, times(1)).execute(any(InventoryEntryQuery.class)); - // verify(sourceClient, times(1)).execute(any(CartDiscountQuery.class)); - // verify(sourceClient, times(1)).execute(any(StateQuery.class)); - // verify(sourceClient, times(1)).execute(any(CustomObjectQuery.class)); - // verify(sourceClient, times(1)).execute(any(CustomerQuery.class)); - // verify(sourceClient, times(1)).execute(any(ShoppingListQuery.class)); - // } - // - // @Test - // void run_WithSyncAsArgumentWithAllArg_ShouldExecuteAllSyncersInCorrectOrder() { - // // preparation - // final SphereClient sourceClient = mock(SphereClient.class); - // when(sourceClient.getConfig()).thenReturn(SphereClientConfig.of("foo", "foo", "foo")); - // - // final SphereClient targetClient = mock(SphereClient.class); - // when(targetClient.getConfig()).thenReturn(SphereClientConfig.of("bar", "bar", "bar")); - // - // when(sourceClient.execute(any(ProductTypeQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // when(sourceClient.execute(any(TypeQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // when(sourceClient.execute(any(CategoryQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // when(sourceClient.execute(any(InventoryEntryQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // when(sourceClient.execute(any(ProductProjectionQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // when(sourceClient.execute(any(CartDiscountQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // when(sourceClient.execute(any(StateQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // when(sourceClient.execute(any(TaxCategoryQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // when(sourceClient.execute(any(CustomObjectQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // when(sourceClient.execute(any(CustomerQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // when(sourceClient.execute(any(ShoppingListQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(PagedQueryResult.empty())); - // - // stubClientsCustomObjectService(targetClient, ZonedDateTime.now()); - // - // final SyncerFactory syncerFactory = - // spy(SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock())); - // - // // test - // CliRunner.of().run(new String[] {"-s", "all", "-f"}, syncerFactory); - // - // // assertions - // verify(syncerFactory, times(1)).sync(new String[] {"all"}, null, true, false, null); - // - // final InOrder inOrder = Mockito.inOrder(sourceClient); - // - // // Resources are grouped based on their references count. - // // Each group will run sequentially but the sync within the group runs in parallel. - // // So verifying the order of one resource in each group. - // inOrder.verify(sourceClient).execute(any(ProductTypeQuery.class)); - // verify(sourceClient, times(1)).execute(any(TypeQuery.class)); - // verify(sourceClient, times(1)).execute(any(CustomObjectQuery.class)); - // verify(sourceClient, times(1)).execute(any(StateQuery.class)); - // verify(sourceClient, times(1)).execute(any(TaxCategoryQuery.class)); - // - // inOrder.verify(sourceClient).execute(any(InventoryEntryQuery.class)); - // verify(sourceClient, times(1)).execute(any(CategoryQuery.class)); - // verify(sourceClient, times(1)).execute(any(CartDiscountQuery.class)); - // verify(sourceClient, times(1)).execute(any(CustomerQuery.class)); - // - // inOrder.verify(sourceClient).execute(any(ProductProjectionQuery.class)); - // - // inOrder.verify(sourceClient).execute(any(ShoppingListQuery.class)); - // - // verify(sourceClient, times(1)).close(); - // verify(sourceClient, times(11)).getConfig(); - // } - // - // @Test - // void run_WithOnlySyncCustomObjectArgument_ShouldThrowException() { - // // preparation - // final SphereClient sourceClient = mock(SphereClient.class); - // when(sourceClient.getConfig()).thenReturn(SphereClientConfig.of("foo", "foo", "foo")); - // - // final SphereClient targetClient = mock(SphereClient.class); - // when(targetClient.getConfig()).thenReturn(SphereClientConfig.of("bar", "bar", "bar")); - // - // final SyncerFactory syncerFactory = - // spy(SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock())); - // - // // test - // CliRunner.of().run(new String[] {"--syncProjectSyncCustomObjects"}, syncerFactory); - // - // // assertions - // assertThat(testLogger.getAllLoggingEvents()) - // .hasSize(1) - // .singleElement() - // .satisfies( - // loggingEvent -> { - // assertThat(loggingEvent.getLevel()).isEqualTo(Level.ERROR); - // assertThat(loggingEvent.getMessage()).contains("Failed to run sync process."); - // final Optional actualThrowableOpt = loggingEvent.getThrowable(); - // assertThat(actualThrowableOpt).isNotNull(); - // assertThat(actualThrowableOpt.isPresent()).isTrue(); - // final Throwable actualThrowable = actualThrowableOpt.get(); - // assertThat(actualThrowable).isExactlyInstanceOf(CliException.class); - // assertThat(actualThrowable.getMessage()) - // .isEqualTo( - // format( - // "Please pass at least 1 more option other than %s to the CLI.", - // CliRunner.SYNC_PROJECT_SYNC_CUSTOM_OBJECTS_OPTION_LONG)); - // }); - // } + @Test + void run_WithSyncAsArgumentWithNoArgs_ShouldFailAndLogError() { + // preparation + final SyncerFactory syncerFactory = + SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock()); + + // test + CliRunner.of().run(new String[] {"-s"}, syncerFactory); + + // assertion + assertThat(testLogger.getAllLoggingEvents()) + .hasSize(1) + .singleElement() + .satisfies( + loggingEvent -> { + assertThat(loggingEvent.getLevel()).isEqualTo(Level.ERROR); + assertThat(loggingEvent.getMessage()).contains("Failed to run sync process."); + final Optional actualThrowableOpt = loggingEvent.getThrowable(); + assertThat(actualThrowableOpt).isNotNull(); + assertThat(actualThrowableOpt.isPresent()).isTrue(); + final Throwable actualThrowable = actualThrowableOpt.get(); + assertThat(actualThrowable).isExactlyInstanceOf(CliException.class); + assertThat(actualThrowable.getMessage()).contains("Missing argument for option: s"); + }); + } + + @Test + void run_WithFullSyncAsFirstArgument_ShouldFailAndLogError() { + // preparation + final SyncerFactory syncerFactory = + SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock()); + + // test + CliRunner.of().run(new String[] {"-f"}, syncerFactory); + + // assertion + assertThat(testLogger.getAllLoggingEvents()) + .hasSize(1) + .singleElement() + .satisfies( + loggingEvent -> { + assertThat(loggingEvent.getLevel()).isEqualTo(Level.ERROR); + assertThat(loggingEvent.getMessage()).contains("Failed to run sync process."); + final Optional actualThrowableOpt = loggingEvent.getThrowable(); + assertThat(actualThrowableOpt).isNotNull(); + assertThat(actualThrowableOpt.isPresent()).isTrue(); + final Throwable actualThrowable = actualThrowableOpt.get(); + assertThat(actualThrowable).isExactlyInstanceOf(CliException.class); + assertThat(actualThrowable.getMessage()) + .contains("Please check that the first sync option is either -s, -h or -v."); + }); + } + + @Test + void run_AsProductDeltaSync_ShouldBuildSyncerAndExecuteSync() { + // preparation + stubClientsCustomObjectService(targetClient, ZonedDateTime.now()); + + final SyncerFactory syncerFactory = + spy(SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock())); + + // test + CliRunner.of().run(new String[] {"-s", "products"}, syncerFactory); + + // assertions + verify(syncerFactory, times(1)).sync(new String[] {"products"}, null, false, false, null); + verify(sourceClient, times(1)).productProjections(); + } + + @Test + void run_AsProductFullSync_ShouldBuildSyncerAndExecuteSync() { + // preparation + stubClientsCustomObjectService(targetClient, ZonedDateTime.now()); + + final SyncerFactory syncerFactory = + spy(SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock())); + + // test + CliRunner.of().run(new String[] {"-s", "products", "-f"}, syncerFactory); + + // assertions + verify(syncerFactory, times(1)).sync(new String[] {"products"}, null, true, false, null); + verify(sourceClient, times(1)).productProjections(); + } + + @Test + void + run_AsProductSyncWithCustomProductQueriesAndLimit_ShouldBuildSyncerAndExecuteQuerySuccessfully() { + // preparation + stubClientsCustomObjectService(targetClient, ZonedDateTime.now()); + final ByProjectKeyProductProjectionsGet getMock = mock(ByProjectKeyProductProjectionsGet.class); + when(getMock.addStaged(anyBoolean())).thenReturn(getMock); + when(getMock.withLimit(anyLong())).thenReturn(getMock); + when(getMock.withWhere(anyString())).thenReturn(getMock); + when(sourceClient.productProjections()).thenReturn(mock()); + when(sourceClient.productProjections().get()).thenReturn(getMock); + + final Long limit = 100L; + final String customQuery = + "published=true AND masterData(masterVariant(attributes(name=abc AND value=123)))"; + final String productQueryParametersValue = + "{\"limit\": " + limit + ", \"where\": \"" + customQuery + "\"}"; + + final SyncerFactory syncerFactory = + spy(SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock())); + // test + CliRunner.of() + .run( + new String[] { + "-s", "products", "-f", "-productQueryParameters", productQueryParametersValue + }, + syncerFactory); + + // assertions + verify(sourceClient.productProjections(), times(1)).get(); + verify(getMock, times(1)).withLimit(limit); + verify(getMock, times(1)).withWhere(customQuery); + } + + @Test + void + run_AsProductSyncWithProductQueryParametersAndOnlyLimit_ShouldBuildSyncerAndExecuteQuerySuccessfully() { + // preparation + stubClientsCustomObjectService(targetClient, ZonedDateTime.now()); + final ByProjectKeyProductProjectionsGet getMock = mock(ByProjectKeyProductProjectionsGet.class); + when(getMock.addStaged(anyBoolean())).thenReturn(getMock); + when(getMock.withLimit(anyLong())).thenReturn(getMock); + when(getMock.withWhere(anyString())).thenReturn(getMock); + when(sourceClient.productProjections()).thenReturn(mock()); + when(sourceClient.productProjections().get()).thenReturn(getMock); + + final Long limit = 100L; + final String productQueryParametersValue = "{\"limit\": " + limit + "}"; + + final SyncerFactory syncerFactory = + spy(SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock())); + + // test + CliRunner.of() + .run( + new String[] { + "-s", "products", "-f", "-productQueryParameters", productQueryParametersValue + }, + syncerFactory); + + // assertions + verify(sourceClient.productProjections(), times(1)).get(); + verify(getMock, times(1)).withLimit(limit); + verify(getMock, times(0)).withWhere(""); + } + + @Test + void + run_AsProductSyncWithProductQueryParametersAndOnlyWhere_ShouldBuildSyncerAndExecuteQuerySuccessfully() { + // preparation + stubClientsCustomObjectService(targetClient, ZonedDateTime.now()); + + final ByProjectKeyProductProjectionsGet getMock = mock(ByProjectKeyProductProjectionsGet.class); + when(getMock.addStaged(anyBoolean())).thenReturn(getMock); + when(getMock.withLimit(anyLong())).thenReturn(getMock); + when(getMock.withWhere(anyString())).thenReturn(getMock); + when(sourceClient.productProjections()).thenReturn(mock()); + when(sourceClient.productProjections().get()).thenReturn(getMock); + + final String customQuery = + "published=true AND masterVariant(attributes(name= \\\"abc\\\" AND value=123))"; + final String productQueryParametersValue = "{\"where\": \"" + customQuery + "\"}"; + + final SyncerFactory syncerFactory = + spy(SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock())); + + // test + CliRunner.of() + .run( + new String[] { + "-s", "products", "-f", "-productQueryParameters", productQueryParametersValue + }, + syncerFactory); + + // assertions + verify(sourceClient.productProjections(), times(1)).get(); + verify(getMock, times(0)).withLimit(1L); + verify(getMock, times(1)) + .withWhere("published=true AND masterVariant(attributes(name= \"abc\" AND value=123))"); + } + + @Test + void run_WithWrongFormatProductQueryParametersArgument_ShouldThrowCLIException() { + // preparation + final Long limit = 100L; + final String customQuery = + "\"published=true AND masterVariant(attributes(name= \"abc\\\" AND value=123))\""; + final String productQueryParametersValue = + "{\"limit\": " + limit + ", \"where\": " + customQuery + "}"; + + final SyncerFactory syncerFactory = + spy(SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock())); + + // test + CliRunner.of() + .run( + new String[] { + "-s", "products", "-f", "-productQueryParameters", productQueryParametersValue + }, + syncerFactory); + + // assertion + assertThat(testLogger.getAllLoggingEvents()) + .hasSize(1) + .singleElement() + .satisfies( + loggingEvent -> { + assertThat(loggingEvent.getLevel()).isEqualTo(Level.ERROR); + assertThat(loggingEvent.getMessage()).contains("Failed to run sync process."); + final Optional actualThrowableOpt = loggingEvent.getThrowable(); + assertThat(actualThrowableOpt).isNotNull(); + assertThat(actualThrowableOpt.isPresent()).isTrue(); + final Throwable actualThrowable = actualThrowableOpt.get(); + assertThat(actualThrowable).isExactlyInstanceOf(CliException.class); + }); + } + + @Test + void run_WithInvalidLimitInProductQueryParametersArgument_ShouldThrowCLIException() { + // preparation + final Long limit = -100L; + final String customQuery = + "\"published=true AND masterVariant(attributes(name= \"abc\\\" AND value=123))\""; + final String productQueryParametersValue = + "{\"limit\": " + limit + ", \"where\": " + customQuery + "}"; + + final SyncerFactory syncerFactory = + spy(SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock())); + + // test + CliRunner.of() + .run( + new String[] { + "-s", "products", "-f", "-productQueryParameters", productQueryParametersValue + }, + syncerFactory); + + // assertion + assertThat(testLogger.getAllLoggingEvents()) + .hasSize(1) + .singleElement() + .satisfies( + loggingEvent -> { + assertThat(loggingEvent.getLevel()).isEqualTo(Level.ERROR); + assertThat(loggingEvent.getMessage()).contains("Failed to run sync process."); + final Optional actualThrowableOpt = loggingEvent.getThrowable(); + assertThat(actualThrowableOpt).isNotNull(); + assertThat(actualThrowableOpt.isPresent()).isTrue(); + final Throwable actualThrowable = actualThrowableOpt.get(); + assertThat(actualThrowable).isExactlyInstanceOf(CliException.class); + assertThat(actualThrowable.getMessage()) + .contains("limit -100 cannot be less than 1."); + }); + } + + @Test + void run_AsTaxCategoryDeltaSync_ShouldBuildSyncerAndExecuteSync() { + // preparation + stubClientsCustomObjectService(targetClient, ZonedDateTime.now()); + final SyncerFactory syncerFactory = + spy(SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock())); + + // test + CliRunner.of().run(new String[] {"-s", "taxCategories"}, syncerFactory); + + // assertions + verify(syncerFactory, times(1)).sync(new String[] {"taxCategories"}, null, false, false, null); + verify(sourceClient, times(1)).taxCategories(); + } + + @Test + void run_AsTaxCategoryFullSync_ShouldBuildSyncerAndExecuteSync() { + // preparation + stubClientsCustomObjectService(targetClient, ZonedDateTime.now()); + + final SyncerFactory syncerFactory = + spy(SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock())); + + // test + CliRunner.of().run(new String[] {"-s", "taxCategories", "-f"}, syncerFactory); + + // assertions + verify(syncerFactory, times(1)).sync(new String[] {"taxCategories"}, null, true, false, null); + verify(sourceClient, times(1)).taxCategories(); + } + + @Test + void run_AsCustomerDeltaSync_ShouldBuildSyncerAndExecuteSync() { + // preparation + stubClientsCustomObjectService(targetClient, ZonedDateTime.now()); + final SyncerFactory syncerFactory = + spy(SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock())); + + // test + CliRunner.of().run(new String[] {"-s", "customers"}, syncerFactory); + + // assertions + verify(syncerFactory, times(1)).sync(new String[] {"customers"}, null, false, false, null); + verify(sourceClient, times(1)).customers(); + } + + @Test + void run_AsCustomerFullSync_ShouldBuildSyncerAndExecuteSync() { + // preparation + stubClientsCustomObjectService(targetClient, ZonedDateTime.now()); + final SyncerFactory syncerFactory = + spy(SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock())); + + // test + CliRunner.of().run(new String[] {"-s", "customers", "-f"}, syncerFactory); + + // assertions + verify(syncerFactory, times(1)).sync(new String[] {"customers"}, null, true, false, null); + verify(sourceClient, times(1)).customers(); + } + + @Test + void run_AsShoppingListDeltaSync_ShouldBuildSyncerAndExecuteSync() { + // preparation + stubClientsCustomObjectService(targetClient, ZonedDateTime.now()); + final SyncerFactory syncerFactory = + spy(SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock())); + + // test + CliRunner.of().run(new String[] {"-s", "shoppingLists"}, syncerFactory); + + // assertions + verify(syncerFactory, times(1)).sync(new String[] {"shoppingLists"}, null, false, false, null); + verify(sourceClient, times(1)).shoppingLists(); + } + + @Test + void run_AsShoppingListFullSync_ShouldBuildSyncerAndExecuteSync() { + // preparation + stubClientsCustomObjectService(targetClient, ZonedDateTime.now()); + + final SyncerFactory syncerFactory = + spy(SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock())); + + // test + CliRunner.of().run(new String[] {"-s", "shoppingLists", "-f"}, syncerFactory); + + // assertions + verify(syncerFactory, times(1)).sync(new String[] {"shoppingLists"}, null, true, false, null); + verify(sourceClient, times(1)).shoppingLists(); + } + + @Test + void run_AsCustomObjectDeltaSync_ShouldBuildSyncerAndExecuteSync() { + // preparation + stubClientsCustomObjectService(targetClient, ZonedDateTime.now()); + + final SyncerFactory syncerFactory = + spy(SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock())); + + // test + CliRunner.of().run(new String[] {"-s", "customObjects"}, syncerFactory); + + // assertions + verify(syncerFactory, times(1)).sync(new String[] {"customObjects"}, null, false, false, null); + verify(sourceClient, times(1)).customObjects(); + } + + @Test + void run_AsCustomObjectFullSync_ShouldBuildSyncerAndExecuteSync() { + // preparation + stubClientsCustomObjectService(targetClient, ZonedDateTime.now()); + final SyncerFactory syncerFactory = + spy(SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock())); + + // test + CliRunner.of().run(new String[] {"-s", "customObjects", "-f"}, syncerFactory); + + // assertions + verify(syncerFactory, times(1)).sync(new String[] {"customObjects"}, null, true, false, null); + verify(sourceClient, times(1)).customObjects(); + } + + @Test + void run_AsCartDiscountFullSync_ShouldBuildSyncerAndExecuteSync() { + // preparation + final SyncerFactory syncerFactory = + spy(SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock())); + + stubClientsCustomObjectService(targetClient, ZonedDateTime.now()); + + // test + CliRunner.of().run(new String[] {"-s", "cartDiscounts", "-f"}, syncerFactory); + + // assertions + verify(syncerFactory, times(1)).sync(new String[] {"cartDiscounts"}, null, true, false, null); + verify(sourceClient, times(1)).cartDiscounts(); + } + + @Test + void run_AsStateFullSync_ShouldBuildSyncerAndExecuteSync() { + // preparation + stubClientsCustomObjectService(targetClient, ZonedDateTime.now()); + final SyncerFactory syncerFactory = + spy(SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock())); + + // test + CliRunner.of().run(new String[] {"-s", "states", "-f"}, syncerFactory); + + // assertions + verify(syncerFactory, times(1)).sync(new String[] {"states"}, null, true, false, null); + verify(sourceClient, times(1)).states(); + } + + @Test + void run_WithSyncAsLongArgument_ShouldBuildSyncerAndExecuteSync() { + // preparation + stubClientsCustomObjectService(targetClient, ZonedDateTime.now()); + final SyncerFactory syncerFactory = + spy(SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock())); + + // test + CliRunner.of().run(new String[] {"--sync", "products"}, syncerFactory); + + // assertions + verify(syncerFactory, times(1)).sync(new String[] {"products"}, null, false, false, null); + verify(sourceClient, times(1)).productProjections(); + } + + @Test + void run_WithRunnerName_ShouldProcessSyncOption() { + // preparation + stubClientsCustomObjectService(targetClient, ZonedDateTime.now()); + + final SyncerFactory syncerFactory = + spy(SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock())); + + // test + CliRunner.of().run(new String[] {"--sync", "products", "-r", "Runner123"}, syncerFactory); + + // assertions + verify(syncerFactory, times(1)) + .sync(new String[] {"products"}, "Runner123", false, false, null); + verify(sourceClient, times(1)).productProjections(); + } + + @Test + void run_WithRunnerNameLong_ShouldProcessSyncOption() { + // preparation + stubClientsCustomObjectService(targetClient, ZonedDateTime.now()); + + final SyncerFactory syncerFactory = + spy(SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock())); + + // test + CliRunner.of() + .run( + new String[] {"--sync", "products", "--runnerName", "Runner123", "--full"}, + syncerFactory); + + // assertions + verify(syncerFactory, times(1)).sync(new String[] {"products"}, "Runner123", true, false, null); + verify(sourceClient, times(1)).productProjections(); + } + + @Test + void run_WithUnknownArgument_ShouldPrintAndLogError() { + // preparation + final SyncerFactory syncerFactory = + spy( + SyncerFactory.of( + () -> mock(ProjectApiRoot.class), + () -> mock(ProjectApiRoot.class), + getMockedClock())); + // test + CliRunner.of().run(new String[] {"-u"}, syncerFactory); + + // Assert error log + verify(syncerFactory, never()).sync(any(), any(), anyBoolean(), anyBoolean(), any()); + } + + @Test + void run_WithHelpAsArgument_ShouldPrintThreeOptionsWithDescriptionsToSystemOut() + throws UnsupportedEncodingException { + // preparation + final SyncerFactory syncerFactory = + spy( + SyncerFactory.of( + () -> mock(ProjectApiRoot.class), + () -> mock(ProjectApiRoot.class), + getMockedClock())); + + // test + CliRunner.of().run(new String[] {"-h"}, syncerFactory); + + // assertions + assertThat(testLogger.getAllLoggingEvents()).isEmpty(); + + // Remove line breaks from output stream string. + final String outputStreamWithoutLineBreaks = outputStream.toString("UTF-8").replace("\n", ""); + + // Replace multiple spaces with single space in output stream string. + final String outputStreamWithSingleSpaces = + outputStreamWithoutLineBreaks.trim().replaceAll(" +", " "); + + assertThat(outputStreamWithSingleSpaces) + .contains( + format("-%s,--%s %s", HELP_OPTION_SHORT, HELP_OPTION_LONG, HELP_OPTION_DESCRIPTION)) + .contains( + format( + "-%s,--%s %s", + SYNC_MODULE_OPTION_SHORT, SYNC_MODULE_OPTION_LONG, SYNC_MODULE_OPTION_DESCRIPTION)) + .contains( + format( + "-%s,--%s %s", + RUNNER_NAME_OPTION_SHORT, RUNNER_NAME_OPTION_LONG, RUNNER_NAME_OPTION_DESCRIPTION)) + .contains( + format( + "-%s,--%s %s", + VERSION_OPTION_SHORT, VERSION_OPTION_LONG, VERSION_OPTION_DESCRIPTION)); + verify(syncerFactory, never()).sync(any(), any(), anyBoolean(), anyBoolean(), any()); + } + + @Test + void run_WithSyncAsArgumentWithAllArg_ShouldExecuteAllSyncers() { + // preparation + stubClientsCustomObjectService(targetClient, ZonedDateTime.now()); + + final SyncerFactory syncerFactory = + spy(SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock())); + + // test + CliRunner.of().run(new String[] {"-s", "all"}, syncerFactory); + + // assertions + verify(syncerFactory, times(1)).sync(new String[] {"all"}, null, false, false, null); + verify(sourceClient, times(1)).productTypes(); + verify(sourceClient, times(1)).types(); + verify(sourceClient, times(1)).taxCategories(); + verify(sourceClient, times(1)).categories(); + verify(sourceClient, times(1)).productProjections(); + verify(sourceClient, times(1)).inventory(); + verify(sourceClient, times(1)).cartDiscounts(); + verify(sourceClient, times(1)).states(); + verify(sourceClient, times(1)).customObjects(); + verify(sourceClient, times(1)).customers(); + verify(sourceClient, times(1)).shoppingLists(); + } + + @Test + void run_WithSyncAsArgumentWithAllArgWithRunnerName_ShouldExecuteAllSyncers() { + // preparation + stubClientsCustomObjectService(targetClient, ZonedDateTime.now()); + + final SyncerFactory syncerFactory = + spy(SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock())); + + // test + CliRunner.of().run(new String[] {"-s", "all", "-r", "myRunner"}, syncerFactory); + + // assertions + verify(syncerFactory, times(1)).sync(new String[] {"all"}, "myRunner", false, false, null); + verify(sourceClient, times(1)).productTypes(); + verify(sourceClient, times(1)).types(); + verify(sourceClient, times(1)).taxCategories(); + verify(sourceClient, times(1)).categories(); + verify(sourceClient, times(1)).productProjections(); + verify(sourceClient, times(1)).inventory(); + verify(sourceClient, times(1)).cartDiscounts(); + verify(sourceClient, times(1)).states(); + verify(sourceClient, times(1)).customObjects(); + verify(sourceClient, times(1)).customers(); + verify(sourceClient, times(1)).shoppingLists(); + } + + @Test + void run_WithSyncAsArgumentWithAllArg_ShouldExecuteAllSyncersInCorrectOrder() { + // preparation + stubClientsCustomObjectService(targetClient, ZonedDateTime.now()); + + final SyncerFactory syncerFactory = + spy(SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock())); + + // test + CliRunner.of().run(new String[] {"-s", "all", "-f"}, syncerFactory); + + // assertions + verify(syncerFactory, times(1)).sync(new String[] {"all"}, null, true, false, null); + + final InOrder inOrder = Mockito.inOrder(sourceClient); + + // Resources are grouped based on their references count. + // Each group will run sequentially but the sync within the group runs in parallel. + // So verifying the order of one resource in each group. + inOrder.verify(sourceClient).productTypes(); + verify(sourceClient, times(1)).types(); + verify(sourceClient, times(1)).customObjects(); + verify(sourceClient, times(1)).states(); + verify(sourceClient, times(1)).taxCategories(); + + inOrder.verify(sourceClient).inventory(); + verify(sourceClient, times(1)).categories(); + verify(sourceClient, times(1)).cartDiscounts(); + verify(sourceClient, times(1)).customers(); + + inOrder.verify(sourceClient).productProjections(); + + inOrder.verify(sourceClient).shoppingLists(); + + verify(sourceClient, times(1)).close(); + // verify(sourceClient, times(11)).getConfig + } + + @Test + void run_WithOnlySyncCustomObjectArgument_ShouldThrowException() { + // preparation + final SyncerFactory syncerFactory = + spy(SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock())); + + // test + CliRunner.of().run(new String[] {"--syncProjectSyncCustomObjects"}, syncerFactory); + + // assertions + assertThat(testLogger.getAllLoggingEvents()) + .hasSize(1) + .singleElement() + .satisfies( + loggingEvent -> { + assertThat(loggingEvent.getLevel()).isEqualTo(Level.ERROR); + assertThat(loggingEvent.getMessage()).contains("Failed to run sync process."); + final Optional actualThrowableOpt = loggingEvent.getThrowable(); + assertThat(actualThrowableOpt).isNotNull(); + assertThat(actualThrowableOpt.isPresent()).isTrue(); + final Throwable actualThrowable = actualThrowableOpt.get(); + assertThat(actualThrowable).isExactlyInstanceOf(CliException.class); + assertThat(actualThrowable.getMessage()) + .isEqualTo( + format( + "Please pass at least 1 more option other than %s to the CLI.", + CliRunner.SYNC_PROJECT_SYNC_CUSTOM_OBJECTS_OPTION_LONG)); + }); + } } From 6dc800588f47f7c66e8c1cb2e3fd229636f978de Mon Sep 17 00:00:00 2001 From: salander85 Date: Tue, 17 Oct 2023 17:52:53 +0200 Subject: [PATCH 06/14] Cleanup test code --- .../project/sync/SyncerFactoryTest.java | 292 +++++------------- 1 file changed, 84 insertions(+), 208 deletions(-) diff --git a/src/test/java/com/commercetools/project/sync/SyncerFactoryTest.java b/src/test/java/com/commercetools/project/sync/SyncerFactoryTest.java index 8a9e1e3b..f178d25b 100644 --- a/src/test/java/com/commercetools/project/sync/SyncerFactoryTest.java +++ b/src/test/java/com/commercetools/project/sync/SyncerFactoryTest.java @@ -126,35 +126,13 @@ class SyncerFactoryTest { private ProjectApiRoot sourceClient; private ProjectApiRoot targetClient; - private AtomicInteger verifyProductTypesGetCounter, - verifyTypesGetCounter, - verifyStatesGetCounter, - verifyTaxCategoriesGetCounter, - verifyCategoriesGetCounter, - verifyInventoryGetCounter, - verifyProductProjectionsGetCounter, - verifyCartDiscountsGetCounter, - verifyCustomersGetCounter, - verifyCustomObjectsGetCounter, - verifyShoppingListsGetCounter, - verifyInvokeClientCounter; - @BeforeEach void setupTest() { - verifyProductTypesGetCounter = new AtomicInteger(0); - verifyTypesGetCounter = new AtomicInteger(0); - verifyStatesGetCounter = new AtomicInteger(0); - verifyTaxCategoriesGetCounter = new AtomicInteger(0); - verifyCategoriesGetCounter = new AtomicInteger(0); - verifyInventoryGetCounter = new AtomicInteger(0); - verifyProductProjectionsGetCounter = new AtomicInteger(0); - verifyCustomObjectsGetCounter = new AtomicInteger(0); - verifyCustomersGetCounter = new AtomicInteger(0); - verifyCartDiscountsGetCounter = new AtomicInteger(0); - verifyShoppingListsGetCounter = new AtomicInteger(0); - verifyInvokeClientCounter = new AtomicInteger(0); - sourceClient = mockClientResourceRequests("testProjectKey"); + final ProjectApiRoot clientWithEmptyResourceResults = + mockClientResourceRequests("testProjectKey"); + sourceClient = spy(clientWithEmptyResourceResults); targetClient = mock(ProjectApiRoot.class); + when(targetClient.getProjectKey()).thenReturn("testTargetProjectKey"); } @AfterEach @@ -178,40 +156,6 @@ private ProjectApiRoot mockClientResourceRequests(final String projectKey) { projectKey, (uri, method, encodedRequetsBody) -> { final String responseString = "{\"results\":[]}"; - if (uri.contains("product-types") && ApiHttpMethod.GET.equals(method)) { - verifyProductTypesGetCounter.incrementAndGet(); - } - if (uri.contains("types") && ApiHttpMethod.GET.equals(method)) { - verifyTypesGetCounter.incrementAndGet(); - } - if (uri.contains("states") && ApiHttpMethod.GET.equals(method)) { - verifyStatesGetCounter.incrementAndGet(); - } - if (uri.contains("tax-categories") && ApiHttpMethod.GET.equals(method)) { - verifyTaxCategoriesGetCounter.incrementAndGet(); - } - if (uri.contains("categories") && ApiHttpMethod.GET.equals(method)) { - verifyCategoriesGetCounter.incrementAndGet(); - } - if (uri.contains("inventory?") && ApiHttpMethod.GET.equals(method)) { - verifyInventoryGetCounter.incrementAndGet(); - } - if (uri.contains("product-projections") && ApiHttpMethod.GET.equals(method)) { - verifyProductProjectionsGetCounter.incrementAndGet(); - } - if (uri.contains("cart-discounts") && ApiHttpMethod.GET.equals(method)) { - verifyCartDiscountsGetCounter.incrementAndGet(); - } - if (uri.contains("custom-objects") && ApiHttpMethod.GET.equals(method)) { - verifyCustomObjectsGetCounter.incrementAndGet(); - } - if (uri.contains("customers") && ApiHttpMethod.GET.equals(method)) { - verifyCustomersGetCounter.incrementAndGet(); - } - if (uri.contains("shopping-lists") && ApiHttpMethod.GET.equals(method)) { - verifyShoppingListsGetCounter.incrementAndGet(); - } - verifyInvokeClientCounter.incrementAndGet(); return CompletableFuture.completedFuture( new ApiHttpResponse<>(200, null, responseString.getBytes(StandardCharsets.UTF_8))); }); @@ -265,29 +209,25 @@ void sync_WithUnknownOptionValue_ShouldCompleteExceptionallyWithIllegalArgumentE @SuppressWarnings("unchecked") void sync_AsProductsDeltaSync_ShouldBuildSyncerAndExecuteSync() { // preparation - final ProjectApiRoot sourceClientSpy = spy(sourceClient); final ZonedDateTime currentCtpTimestamp = ZonedDateTime.now(); - final ProjectApiRoot targetClientMock = mock(ProjectApiRoot.class); - when(targetClientMock.getProjectKey()).thenReturn("testProjectKey"); - stubClientsCustomObjectService(targetClientMock, currentCtpTimestamp); + stubClientsCustomObjectService(targetClient, currentCtpTimestamp); final SyncerFactory syncerFactory = - SyncerFactory.of(() -> sourceClientSpy, () -> targetClientMock, getMockedClock()); + SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock()); // test syncerFactory.sync(new String[] {"products"}, "myRunnerName", false, false, null); // assertions // verify product-projections are queried once - verify(sourceClientSpy, times(1)).productProjections(); - assertThat(verifyProductProjectionsGetCounter.get()).isEqualTo(1); - verifyTimestampGeneratorCustomObjectUpsertIsCalled( - targetClientMock, "ProductSync", "myRunnerName"); + verify(sourceClient, times(1)).productProjections(); + // assertThat(verifyProductProjectionsGetCounter.get()).isEqualTo(1); + verifyTimestampGeneratorCustomObjectUpsertIsCalled(targetClient, "ProductSync", "myRunnerName"); verifyLastSyncCustomObjectQuery( - targetClientMock, "productSync", "myRunnerName", "testProjectKey", 1); + targetClient, "productSync", "myRunnerName", "testProjectKey", 1); // verify two custom object upserts : 1. current ctp timestamp and 2. last sync timestamp // creation) - verify(targetClientMock.customObjects(), times(2)).post(any(CustomObjectDraft.class)); + verify(targetClient.customObjects(), times(2)).post(any(CustomObjectDraft.class)); // TODO: Assert on actual last sync timestamp creation in detail after Statistics classes in // java-sync library // TODO: override #equals method: @@ -295,7 +235,7 @@ void sync_AsProductsDeltaSync_ShouldBuildSyncerAndExecuteSync() { // TODO: e.g. verifyNewLastSyncCustomObjectCreation(targetClient, // currentCtpTimestamp.minusMinutes(2), any(ProductSyncStatistics.class), 0L, "productSync", // "foo"); - verifyInteractionsWithClientAfterSync(sourceClientSpy, 1); + verifyInteractionsWithClientAfterSync(sourceClient, 1); final Condition startLog = new Condition<>( @@ -325,27 +265,23 @@ void sync_AsProductsDeltaSync_ShouldBuildSyncerAndExecuteSync() { @SuppressWarnings("unchecked") void sync_AsProductsFullSync_ShouldBuildSyncerAndExecuteSync() { // preparation - final ProjectApiRoot sourceClientSpy = spy(sourceClient); final ZonedDateTime currentCtpTimestamp = ZonedDateTime.now(); - final ProjectApiRoot targetClient = mock(ProjectApiRoot.class); - when(targetClient.getProjectKey()).thenReturn("testTargetProjectKey"); stubClientsCustomObjectService(targetClient, currentCtpTimestamp); final SyncerFactory syncerFactory = - SyncerFactory.of(() -> sourceClientSpy, () -> targetClient, getMockedClock()); + SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock()); // test syncerFactory.sync(new String[] {"products"}, "myRunnerName", true, false, null); // assertions - verify(sourceClientSpy, times(1)).productProjections(); - assertThat(verifyProductProjectionsGetCounter.get()).isEqualTo(1); - + verify(sourceClient, times(1)).productProjections(); + // assertThat(verifyProductProjectionsGetCounter.get()).isEqualTo(1); verifyTimestampGeneratorCustomObjectUpsertIsNotCalled( targetClient, "ProductSync", "myRunnerName"); verifyLastSyncCustomObjectQuery(targetClient, "productSync", "myRunnerName", "foo", 0); verify(targetClient.customObjects(), times(0)).post(any(CustomObjectDraft.class)); - verifyInteractionsWithClientAfterSync(sourceClientSpy, 1); + verifyInteractionsWithClientAfterSync(sourceClient, 1); final Condition startLog = new Condition<>( @@ -392,6 +328,7 @@ void sync_AsProductsFullSync_ShouldBuildSyncerAndExecuteSync() { .total(2L) .build(); + final AtomicInteger verifyProductProjectionsGetCounter = new AtomicInteger(0); final BadGatewayException badGatewayException = createBadGatewayException(); final ProjectApiRoot sourceClient = withTestClient( @@ -400,7 +337,6 @@ void sync_AsProductsFullSync_ShouldBuildSyncerAndExecuteSync() { if (uri.contains("graphql") && ApiHttpMethod.POST.equals(method)) { return CompletableFutureUtils.failed(badGatewayException); } - verifyInvokeClientCounter.incrementAndGet(); if (uri.contains("product-projections") && ApiHttpMethod.GET.equals(method)) { if (verifyProductProjectionsGetCounter.get() == 0) { verifyProductProjectionsGetCounter.incrementAndGet(); @@ -414,8 +350,6 @@ void sync_AsProductsFullSync_ShouldBuildSyncerAndExecuteSync() { return null; }); - final ProjectApiRoot targetClient = mock(ProjectApiRoot.class); - when(targetClient.getProjectKey()).thenReturn("testTargetProjectKey"); stubClientsCustomObjectService(targetClient, ZonedDateTime.now()); final ByProjectKeyProductsPost byProjectKeyProductsPost = mock(ByProjectKeyProductsPost.class); when(byProjectKeyProductsPost.execute()) @@ -481,6 +415,7 @@ void sync_AsProductsFullSync_ShouldBuildSyncerAndExecuteSync() { void sync_AsProductsFullSyncWithExceptionDuringAttributeReferenceReplacement_ShouldContinueWithPages() { // preparation + final AtomicInteger verifyProductProjectionsGetCounter = new AtomicInteger(0); final AtomicInteger sourceGraphQLPostCounter = new AtomicInteger(0); final ProductProjection product1 = ProductMixin.toProjection( @@ -713,13 +648,6 @@ private static CustomObjectDraft findTimestampGeneratorCustomObjectUpsert( @Nonnull ProjectApiRoot client, @Nonnull String syncMethodName, @Nonnull String syncRunnerName) { - // fact: SphereRequest is a very broad interface and we actually wanted to capture only - // CustomObjectUpsertCommand. - // I tried it but argumentcaptor captures also CustomObjectQueryImpl classes, because we call - // both query and upsert in the mocked ProjectApiRoot. - // This situation throws runtime NPE error later in the method as query doesnt contain a draft. - // I guess generics doesnt work here as type is not know on compile time. - // That's why we need to filter instanceof CustomObjectUpsertCommand in the streams. final ArgumentCaptor customObjectDraftArgumentCaptor = ArgumentCaptor.forClass(CustomObjectDraft.class); @@ -727,7 +655,6 @@ private static CustomObjectDraft findTimestampGeneratorCustomObjectUpsert( final List allValues = customObjectDraftArgumentCaptor.getAllValues(); final CustomObjectDraft customObjectDraft = allValues.stream() - .filter(draft -> draft instanceof CustomObjectDraft) .filter( draft -> draft @@ -777,10 +704,7 @@ private static String createJsonStringFromPagedQueryResponse( @SuppressWarnings("unchecked") void sync_AsCategoriesDeltaSync_ShouldBuildSyncerAndExecuteSync() { // preparation - final ProjectApiRoot sourceClient = mockClientResourceRequests("testSourceProjectKey"); final ZonedDateTime currentCtpTimestamp = ZonedDateTime.now(); - final ProjectApiRoot targetClient = mock(ProjectApiRoot.class); - when(targetClient.getProjectKey()).thenReturn("testTargetProjectKey"); stubClientsCustomObjectService(targetClient, currentCtpTimestamp); final SyncerFactory syncerFactory = @@ -789,11 +713,11 @@ void sync_AsCategoriesDeltaSync_ShouldBuildSyncerAndExecuteSync() { syncerFactory.sync(new String[] {"categories"}, null, false, false, null); // assertions - assertThat(verifyCategoriesGetCounter.get()).isEqualTo(1); + verify(sourceClient, times(1)).categories(); verifyTimestampGeneratorCustomObjectUpsertIsCalled( targetClient, "CategorySync", DEFAULT_RUNNER_NAME); verifyLastSyncCustomObjectQuery( - targetClient, "categorySync", DEFAULT_RUNNER_NAME, "testSourceProjectKey", 1); + targetClient, "categorySync", DEFAULT_RUNNER_NAME, "testProjectKey", 1); // verify two custom object upserts : 1. current ctp timestamp and 2. last sync timestamp verify(targetClient.customObjects(), times(2)).post(any(CustomObjectDraft.class)); // TODO: Assert on actual last sync timestamp creation in detail after Statistics classes in @@ -803,7 +727,7 @@ void sync_AsCategoriesDeltaSync_ShouldBuildSyncerAndExecuteSync() { // TODO: e.g. verifyNewLastSyncCustomObjectCreation(targetClient, // currentCtpTimestamp.minusMinutes(2), any(ProductSyncStatistics.class), 0L, "productSync", // "foo"); - assertThat(verifyInvokeClientCounter.get()).isEqualTo(1); + verifyInteractionsWithClientAfterSync(sourceClient, 1); final Condition startLog = new Condition<>( @@ -833,10 +757,7 @@ void sync_AsCategoriesDeltaSync_ShouldBuildSyncerAndExecuteSync() { @SuppressWarnings("unchecked") void sync_AsProductTypesDeltaSync_ShouldBuildSyncerAndExecuteSync() { // preparation - final ProjectApiRoot sourceClient = mockClientResourceRequests("testSourceProjectKey"); final ZonedDateTime currentCtpTimestamp = ZonedDateTime.now(); - final ProjectApiRoot targetClient = mock(ProjectApiRoot.class); - when(targetClient.getProjectKey()).thenReturn("testTargetProjectKey"); stubClientsCustomObjectService(targetClient, currentCtpTimestamp); final SyncerFactory syncerFactory = @@ -846,11 +767,11 @@ void sync_AsProductTypesDeltaSync_ShouldBuildSyncerAndExecuteSync() { syncerFactory.sync(new String[] {"productTypes"}, "", false, false, null); // assertions - assertThat(verifyProductTypesGetCounter.get()).isEqualTo(1); + verify(sourceClient, times(1)).productTypes(); verifyTimestampGeneratorCustomObjectUpsertIsCalled( targetClient, "ProductTypeSync", DEFAULT_RUNNER_NAME); verifyLastSyncCustomObjectQuery( - targetClient, "productTypeSync", DEFAULT_RUNNER_NAME, "testSourceProjectKey", 1); + targetClient, "productTypeSync", DEFAULT_RUNNER_NAME, "testProjectKey", 1); // verify two custom object upserts : 1. current ctp timestamp and 2. last sync timestamp // creation) verify(targetClient.customObjects(), times(2)).post(any(CustomObjectDraft.class)); @@ -861,7 +782,7 @@ void sync_AsProductTypesDeltaSync_ShouldBuildSyncerAndExecuteSync() { // TODO: e.g. verifyNewLastSyncCustomObjectCreation(targetClient, // currentCtpTimestamp.minusMinutes(2), any(ProductSyncStatistics.class), 0L, "productSync", // "foo"); - assertThat(verifyInvokeClientCounter.get()).isEqualTo(1); + verifyInteractionsWithClientAfterSync(sourceClient, 1); final Condition startLog = new Condition<>( @@ -892,11 +813,8 @@ void sync_AsProductTypesDeltaSync_ShouldBuildSyncerAndExecuteSync() { @SuppressWarnings("unchecked") void sync_AsTypesDeltaSync_ShouldBuildSyncerAndExecuteSync() { // preparation - final ProjectApiRoot sourceClient = mockClientResourceRequests("testSourceProjectKey"); final ZonedDateTime currentCtpTimestamp = ZonedDateTime.now(); - final ProjectApiRoot targetClient = mock(ProjectApiRoot.class); - when(targetClient.getProjectKey()).thenReturn("testTargetProjectKey"); - stubClientsCustomObjectService(targetClient, currentCtpTimestamp); + stubClientsCustomObjectService(targetClient, ZonedDateTime.now()); final SyncerFactory syncerFactory = SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock()); @@ -905,9 +823,9 @@ void sync_AsTypesDeltaSync_ShouldBuildSyncerAndExecuteSync() { syncerFactory.sync(new String[] {"types"}, "foo", false, false, null); // assertions - assertThat(verifyTypesGetCounter.get()).isEqualTo(1); + verify(sourceClient, times(1)).types(); verifyTimestampGeneratorCustomObjectUpsertIsCalled(targetClient, "TypeSync", "foo"); - verifyLastSyncCustomObjectQuery(targetClient, "typeSync", "foo", "testSourceProjectKey", 1); + verifyLastSyncCustomObjectQuery(targetClient, "typeSync", "foo", "testProjectKey", 1); // verify two custom object upserts : 1. current ctp timestamp and 2. last sync timestamp // creation) verify(targetClient.customObjects(), times(2)).post(any(CustomObjectDraft.class)); @@ -918,7 +836,7 @@ void sync_AsTypesDeltaSync_ShouldBuildSyncerAndExecuteSync() { // TODO: e.g. verifyNewLastSyncCustomObjectCreation(targetClient, // currentCtpTimestamp.minusMinutes(2), any(ProductSyncStatistics.class), 0L, "productSync", // "foo"); - assertThat(verifyInvokeClientCounter.get()).isEqualTo(1); + verifyInteractionsWithClientAfterSync(sourceClient, 1); final Condition startLog = new Condition<>( @@ -948,11 +866,7 @@ void sync_AsTypesDeltaSync_ShouldBuildSyncerAndExecuteSync() { @SuppressWarnings("unchecked") void sync_AsInventoryEntriesDeltaSync_ShouldBuildSyncerAndExecuteSync() { // preparation - final ProjectApiRoot sourceClient = mockClientResourceRequests("testSourceProjectKey"); - final ZonedDateTime currentCtpTimestamp = ZonedDateTime.now(); - final ProjectApiRoot targetClient = mock(ProjectApiRoot.class); - when(targetClient.getProjectKey()).thenReturn("testTargetProjectKey"); - stubClientsCustomObjectService(targetClient, currentCtpTimestamp); + stubClientsCustomObjectService(targetClient, ZonedDateTime.now()); final SyncerFactory syncerFactory = SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock()); @@ -961,11 +875,11 @@ void sync_AsInventoryEntriesDeltaSync_ShouldBuildSyncerAndExecuteSync() { syncerFactory.sync(new String[] {"inventoryEntries"}, null, false, false, null); // assertions - assertThat(verifyInventoryGetCounter.get()).isEqualTo(1); + verify(sourceClient, times(1)).inventory(); verifyTimestampGeneratorCustomObjectUpsertIsCalled( targetClient, "InventorySync", DEFAULT_RUNNER_NAME); verifyLastSyncCustomObjectQuery( - targetClient, "inventorySync", DEFAULT_RUNNER_NAME, "testSourceProjectKey", 1); + targetClient, "inventorySync", DEFAULT_RUNNER_NAME, "testProjectKey", 1); // verify two custom object upserts : 1. current ctp timestamp and 2. last sync timestamp // creation) verify(targetClient.customObjects(), times(2)).post(any(CustomObjectDraft.class)); @@ -976,7 +890,7 @@ void sync_AsInventoryEntriesDeltaSync_ShouldBuildSyncerAndExecuteSync() { // TODO: e.g. verifyNewLastSyncCustomObjectCreation(targetClient, // currentCtpTimestamp.minusMinutes(2), any(ProductSyncStatistics.class), 0L, "productSync", // "foo"); - assertThat(verifyInvokeClientCounter.get()).isEqualTo(1); + verifyInteractionsWithClientAfterSync(sourceClient, 1); final Condition startLog = new Condition<>( @@ -1005,23 +919,19 @@ void sync_AsInventoryEntriesDeltaSync_ShouldBuildSyncerAndExecuteSync() { @Test void sync_WithErrorOnFetch_ShouldCloseClientAndCompleteExceptionally() { // preparation - final ProjectApiRoot sourceClient = + final ProjectApiRoot mockSource = withTestClient( "testProjectKey", (uri, method, encodedRequestBody) -> { - verifyInvokeClientCounter.incrementAndGet(); if (uri.contains("inventory") && ApiHttpMethod.GET.equals(method)) { - verifyInventoryGetCounter.incrementAndGet(); return CompletableFutureUtils.exceptionallyCompletedFuture( createBadGatewayException()); } return null; }); + sourceClient = spy(mockSource); - final ZonedDateTime currentCtpTimestamp = ZonedDateTime.now(); - final ProjectApiRoot targetClient = mock(ProjectApiRoot.class); - when(targetClient.getProjectKey()).thenReturn("testTargetProjectKey"); - stubClientsCustomObjectService(targetClient, currentCtpTimestamp); + stubClientsCustomObjectService(targetClient, ZonedDateTime.now()); final SyncerFactory syncerFactory = SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock()); @@ -1033,8 +943,9 @@ void sync_WithErrorOnFetch_ShouldCloseClientAndCompleteExceptionally() { // assertions verifyTimestampGeneratorCustomObjectUpsertIsCalled( targetClient, "InventorySync", DEFAULT_RUNNER_NAME); - assertThat(verifyInventoryGetCounter.get()).isEqualTo(1); - assertThat(verifyInvokeClientCounter.get()).isEqualTo(1); + verify(sourceClient, times(1)).inventory(); + verifyInteractionsWithClientAfterSync(sourceClient, 1); + assertThat(result) .failsWithin(1, TimeUnit.SECONDS) .withThrowableOfType(ExecutionException.class) @@ -1046,10 +957,6 @@ void sync_WithErrorOnFetch_ShouldCloseClientAndCompleteExceptionally() { void sync_WithErrorOnCurrentCtpTimestampUpsert_ShouldCloseClientAndCompleteExceptionallyWithoutSyncing() { // preparation - final ProjectApiRoot sourceClient = mockClientResourceRequests("testSourceProjectKey"); - ProjectApiRoot spy = spy(sourceClient); - final ProjectApiRoot targetClient = mock(ProjectApiRoot.class); - when(targetClient.getProjectKey()).thenReturn("testTargetProjectKey"); final ByProjectKeyCustomObjectsPost customObjectsPost = mock(ByProjectKeyCustomObjectsPost.class); when(customObjectsPost.execute()) @@ -1060,7 +967,7 @@ void sync_WithErrorOnFetch_ShouldCloseClientAndCompleteExceptionally() { .thenReturn(customObjectsPost); final SyncerFactory syncerFactory = - SyncerFactory.of(() -> spy, () -> targetClient, getMockedClock()); + SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock()); // test final CompletionStage result = @@ -1069,8 +976,8 @@ void sync_WithErrorOnFetch_ShouldCloseClientAndCompleteExceptionally() { // assertions verifyTimestampGeneratorCustomObjectUpsertIsCalled( targetClient, "InventorySync", DEFAULT_RUNNER_NAME); - assertThat(verifyInventoryGetCounter.get()).isEqualTo(0); - verifyInteractionsWithClientAfterSync(spy, 1); + verify(sourceClient, times(0)).inventory(); + verifyInteractionsWithClientAfterSync(sourceClient, 1); assertThat(result) .failsWithin(1, TimeUnit.SECONDS) .withThrowableOfType(ExecutionException.class) @@ -1082,9 +989,6 @@ void sync_WithErrorOnFetch_ShouldCloseClientAndCompleteExceptionally() { void sync_WithErrorOnQueryLastSyncTimestamp_ShouldCloseClientAndCompleteExceptionallyWithoutSyncing() { // preparation - final ProjectApiRoot sourceClientSpy = spy(sourceClient); - final ProjectApiRoot targetClient = mock(ProjectApiRoot.class); - when(targetClient.getProjectKey()).thenReturn("testTargetProjectKey"); final ByProjectKeyCustomObjectsPost customObjectsPost = mock(ByProjectKeyCustomObjectsPost.class); final CustomObject lastSyncCustomObjectCustomObject = @@ -1105,7 +1009,7 @@ void sync_WithErrorOnFetch_ShouldCloseClientAndCompleteExceptionally() { .thenReturn(customObjectsPost); final SyncerFactory syncerFactory = - SyncerFactory.of(() -> sourceClientSpy, () -> targetClient, getMockedClock()); + SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock()); // test final CompletionStage result = @@ -1114,8 +1018,8 @@ void sync_WithErrorOnFetch_ShouldCloseClientAndCompleteExceptionally() { // assertions verifyTimestampGeneratorCustomObjectUpsertIsCalled(targetClient, "InventorySync", "bar"); verifyLastSyncCustomObjectQuery(targetClient, "inventorySync", "bar", "testProjectKey", 1); - verify(sourceClientSpy, times(0)).inventory(); - verifyInteractionsWithClientAfterSync(sourceClientSpy, 1); + verify(sourceClient, times(0)).inventory(); + verifyInteractionsWithClientAfterSync(sourceClient, 1); assertThat(result) .failsWithin(1, TimeUnit.SECONDS) .withThrowableOfType(ExecutionException.class) @@ -1126,13 +1030,9 @@ void sync_WithErrorOnFetch_ShouldCloseClientAndCompleteExceptionally() { @SuppressWarnings("unchecked") void syncAll_AsDelta_ShouldBuildSyncerAndExecuteSync() { // preparation - final ProjectApiRoot sourceClientSpy = spy(sourceClient); - final ZonedDateTime currentCtpTimestamp = ZonedDateTime.now(); - final ProjectApiRoot targetClient = mock(ProjectApiRoot.class); - when(targetClient.getProjectKey()).thenReturn("testTargetProjectKey"); - stubClientsCustomObjectService(targetClient, currentCtpTimestamp); + stubClientsCustomObjectService(targetClient, ZonedDateTime.now()); final SyncerFactory syncerFactory = - SyncerFactory.of(() -> sourceClientSpy, () -> targetClient, getMockedClock()); + SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock()); // test syncerFactory.sync(new String[] {"all"}, null, false, false, null).join(); @@ -1183,18 +1083,18 @@ void syncAll_AsDelta_ShouldBuildSyncerAndExecuteSync() { targetClient, "customerSync", DEFAULT_RUNNER_NAME, "testProjectKey", 1); verifyLastSyncCustomObjectQuery( targetClient, "shoppingListSync", DEFAULT_RUNNER_NAME, "testProjectKey", 1); - verify(sourceClientSpy, times(1)).productTypes(); - verify(sourceClientSpy, times(1)).types(); - verify(sourceClientSpy, times(1)).categories(); - verify(sourceClientSpy, times(1)).productProjections(); - verify(sourceClientSpy, times(1)).inventory(); - verify(sourceClientSpy, times(1)).cartDiscounts(); - verify(sourceClientSpy, times(1)).states(); - verify(sourceClientSpy, times(1)).taxCategories(); - verify(sourceClientSpy, times(1)).customObjects(); - verify(sourceClientSpy, times(1)).customers(); - verify(sourceClientSpy, times(1)).shoppingLists(); - verifyInteractionsWithClientAfterSync(sourceClientSpy, 11); + verify(sourceClient, times(1)).productTypes(); + verify(sourceClient, times(1)).types(); + verify(sourceClient, times(1)).categories(); + verify(sourceClient, times(1)).productProjections(); + verify(sourceClient, times(1)).inventory(); + verify(sourceClient, times(1)).cartDiscounts(); + verify(sourceClient, times(1)).states(); + verify(sourceClient, times(1)).taxCategories(); + verify(sourceClient, times(1)).customObjects(); + verify(sourceClient, times(1)).customers(); + verify(sourceClient, times(1)).shoppingLists(); + verifyInteractionsWithClientAfterSync(sourceClient, 11); assertThat(cliRunnerTestLogger.getAllLoggingEvents()) .allMatch(loggingEvent -> !Level.ERROR.equals(loggingEvent.getLevel())); @@ -1233,13 +1133,9 @@ void syncAll_AsDelta_ShouldBuildSyncerAndExecuteSync() { @SuppressWarnings("unchecked") void syncProductTypesProductsCustomersAndShoppingLists_AsDelta_ShouldBuildSyncerAndExecuteSync() { // preparation - final ProjectApiRoot sourceClientSpy = spy(sourceClient); - final ZonedDateTime currentCtpTimestamp = ZonedDateTime.now(); - final ProjectApiRoot targetClient = mock(ProjectApiRoot.class); - when(targetClient.getProjectKey()).thenReturn("testTargetProjectKey"); - stubClientsCustomObjectService(targetClient, currentCtpTimestamp); + stubClientsCustomObjectService(targetClient, ZonedDateTime.now()); final SyncerFactory syncerFactory = - SyncerFactory.of(() -> sourceClientSpy, () -> targetClient, getMockedClock()); + SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock()); // test String[] syncModuleOptions = {"productTypes", "products", "customers", "shoppingLists"}; @@ -1264,22 +1160,18 @@ void syncProductTypesProductsCustomersAndShoppingLists_AsDelta_ShouldBuildSyncer verifyLastSyncCustomObjectQuery( targetClient, "shoppingListSync", DEFAULT_RUNNER_NAME, "testProjectKey", 1); - final InOrder inOrder = Mockito.inOrder(sourceClientSpy); + final InOrder inOrder = Mockito.inOrder(sourceClient); // According to sync algorithm, ProductType and Customer will run sync in parallel, Product and // ShoppingList sequentially. // Example: Given: ['productTypes', 'customers', 'products', 'shoppingLists'] // From the given arguments, algorithm will group the resources as below, // [productTypes, customers] [products] [shoppingLists] - inOrder.verify(sourceClientSpy, times(1)).productTypes(); - verify(sourceClientSpy, times(1)).customers(); - inOrder.verify(sourceClientSpy, times(1)).productProjections(); - inOrder.verify(sourceClientSpy, times(1)).shoppingLists(); - assertThat(verifyProductTypesGetCounter.get()).isEqualTo(1); - assertThat(verifyCustomersGetCounter.get()).isEqualTo(1); - assertThat(verifyProductProjectionsGetCounter.get()).isEqualTo(1); - assertThat(verifyShoppingListsGetCounter.get()).isEqualTo(1); - verifyInteractionsWithClientAfterSync(sourceClientSpy, 4); + inOrder.verify(sourceClient, times(1)).productTypes(); + verify(sourceClient, times(1)).customers(); + inOrder.verify(sourceClient, times(1)).productProjections(); + inOrder.verify(sourceClient, times(1)).shoppingLists(); + verifyInteractionsWithClientAfterSync(sourceClient, 4); assertProductTypeSyncerLoggingEvents(productTypeSyncerTestLogger, 0); assertProductSyncerLoggingEvents(productSyncerTestLogger, 0); @@ -1291,13 +1183,9 @@ void syncProductTypesProductsCustomersAndShoppingLists_AsDelta_ShouldBuildSyncer @SuppressWarnings("unchecked") void syncStatesInventoryEntriesAndCustomObjects_AsDelta_ShouldBuildSyncerAndExecuteSync() { // preparation - final ProjectApiRoot sourceClientSpy = spy(sourceClient); - final ZonedDateTime currentCtpTimestamp = ZonedDateTime.now(); - final ProjectApiRoot targetClient = mock(ProjectApiRoot.class); - when(targetClient.getProjectKey()).thenReturn("testTargetProjectKey"); - stubClientsCustomObjectService(targetClient, currentCtpTimestamp); + stubClientsCustomObjectService(targetClient, ZonedDateTime.now()); final SyncerFactory syncerFactory = - SyncerFactory.of(() -> sourceClientSpy, () -> targetClient, getMockedClock()); + SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock()); // test String[] syncModuleOptions = {"states", "inventoryEntries", "customObjects"}; @@ -1317,13 +1205,11 @@ void syncStatesInventoryEntriesAndCustomObjects_AsDelta_ShouldBuildSyncerAndExec targetClient, "inventorySync", DEFAULT_RUNNER_NAME, "testProjectKey", 1); verifyLastSyncCustomObjectQuery( targetClient, "customObjectSync", DEFAULT_RUNNER_NAME, "testProjectKey", 1); - verify(sourceClientSpy, times(1)).states(); - verify(sourceClientSpy, times(1)).inventory(); - verify(sourceClientSpy, times(1)).customObjects(); - assertThat(verifyStatesGetCounter.get()).isEqualTo(1); - assertThat(verifyInventoryGetCounter.get()).isEqualTo(1); - assertThat(verifyCustomObjectsGetCounter.get()).isEqualTo(1); - verifyInteractionsWithClientAfterSync(sourceClientSpy, 3); + verify(sourceClient, times(1)).states(); + verify(sourceClient, times(1)).inventory(); + verify(sourceClient, times(1)).customObjects(); + + verifyInteractionsWithClientAfterSync(sourceClient, 3); assertStateSyncerLoggingEvents(stateSyncerTestLogger, 0); assertInventoryEntrySyncerLoggingEvents(inventoryEntrySyncerTestLogger, 0); @@ -1334,14 +1220,10 @@ void syncStatesInventoryEntriesAndCustomObjects_AsDelta_ShouldBuildSyncerAndExec @SuppressWarnings("unchecked") void syncTypesAndCategories_AsDelta_ShouldBuildSyncerAndExecuteSync() { // preparation - final ProjectApiRoot sourceClientSpy = spy(sourceClient); - final ZonedDateTime currentCtpTimestamp = ZonedDateTime.now(); - final ProjectApiRoot targetClient = mock(ProjectApiRoot.class); - when(targetClient.getProjectKey()).thenReturn("testTargetProjectKey"); - stubClientsCustomObjectService(targetClient, currentCtpTimestamp); + stubClientsCustomObjectService(targetClient, ZonedDateTime.now()); final SyncerFactory syncerFactory = - SyncerFactory.of(() -> sourceClientSpy, () -> targetClient, getMockedClock()); + SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock()); // test String[] syncModuleOptions = {"types", "categories"}; @@ -1358,13 +1240,11 @@ void syncTypesAndCategories_AsDelta_ShouldBuildSyncerAndExecuteSync() { verifyLastSyncCustomObjectQuery( targetClient, "categorySync", DEFAULT_RUNNER_NAME, "testProjectKey", 1); - final InOrder inOrder = Mockito.inOrder(sourceClientSpy); + final InOrder inOrder = Mockito.inOrder(sourceClient); - inOrder.verify(sourceClientSpy, times(1)).types(); - inOrder.verify(sourceClientSpy, times(1)).categories(); - assertThat(verifyTypesGetCounter.get()).isEqualTo(1); - assertThat(verifyCategoriesGetCounter.get()).isEqualTo(1); - verifyInteractionsWithClientAfterSync(sourceClientSpy, 2); + inOrder.verify(sourceClient, times(1)).types(); + inOrder.verify(sourceClient, times(1)).categories(); + verifyInteractionsWithClientAfterSync(sourceClient, 2); assertTypeSyncerLoggingEvents(typeSyncerTestLogger, 0); assertCategorySyncerLoggingEvents(categorySyncerTestLogger, 0); @@ -1376,14 +1256,10 @@ void syncTypesAndCategories_AsDelta_ShouldBuildSyncerAndExecuteSync() { @SuppressWarnings("unchecked") void syncProductsAndShoppingLists_AsDelta_ShouldBuildSyncerAndExecuteSync() { // preparation - final ProjectApiRoot sourceSpy = spy(sourceClient); - final ZonedDateTime currentCtpTimestamp = ZonedDateTime.now(); - final ProjectApiRoot targetClient = mock(ProjectApiRoot.class); - when(targetClient.getProjectKey()).thenReturn("testTargetProjectKey"); - stubClientsCustomObjectService(targetClient, currentCtpTimestamp); + stubClientsCustomObjectService(targetClient, ZonedDateTime.now()); final SyncerFactory syncerFactory = - SyncerFactory.of(() -> sourceSpy, () -> targetClient, getMockedClock()); + SyncerFactory.of(() -> sourceClient, () -> targetClient, getMockedClock()); // test String[] syncModuleOptions = {"products", "shoppingLists"}; @@ -1399,9 +1275,9 @@ void syncProductsAndShoppingLists_AsDelta_ShouldBuildSyncerAndExecuteSync() { targetClient, "productSync", DEFAULT_RUNNER_NAME, "testProjectKey", 1); verifyLastSyncCustomObjectQuery( targetClient, "shoppingListSync", DEFAULT_RUNNER_NAME, "testProjectKey", 1); - assertThat(verifyProductProjectionsGetCounter.get()).isEqualTo(1); - assertThat(verifyShoppingListsGetCounter.get()).isEqualTo(1); - verifyInteractionsWithClientAfterSync(sourceSpy, 2); + verify(sourceClient, times(1)).productProjections(); + verify(sourceClient, times(1)).shoppingLists(); + verifyInteractionsWithClientAfterSync(sourceClient, 2); assertProductSyncerLoggingEvents(productSyncerTestLogger, 0); assertShoppingListSyncerLoggingEvents(shoppingListSyncerTestLogger, 0); From 420ccc052877fc62c410b4529a49a8570655b280 Mon Sep 17 00:00:00 2001 From: lojzatran Date: Thu, 19 Oct 2023 12:45:23 +0200 Subject: [PATCH 07/14] DEVX-247 migrate category syncr --- ...CategorySyncWithReferenceResolutionIT.java | 96 +- .../project/sync/CliRunnerIT.java | 2285 +++++++++-------- .../sync/InventorySyncMultiChannelIT.java | 412 +-- .../sync/ProductSyncWithDiscountedPrice.java | 356 +-- .../ProductSyncWithMasterVariantSwitchIT.java | 286 +-- .../ProductSyncWithNestedReferencesIT.java | 996 +++---- .../ProductSyncWithReferenceResolutionIT.java | 617 ++--- .../sync/ProductSyncWithReferencesIT.java | 535 ++-- .../sync/util/IntegrationTestUtils.java | 637 +++-- .../project/sync/util/QueryUtils.java | 135 +- .../project/sync/category/CategorySyncer.java | 2 - .../project/sync/util/CtpClientUtils.java | 5 +- .../sync/category/CategorySyncerTest.java | 398 +-- .../project/sync/util/TestUtils.java | 7 + 14 files changed, 3557 insertions(+), 3210 deletions(-) diff --git a/src/integration-test/java/com/commercetools/project/sync/CategorySyncWithReferenceResolutionIT.java b/src/integration-test/java/com/commercetools/project/sync/CategorySyncWithReferenceResolutionIT.java index c6aa072b..36a155a4 100644 --- a/src/integration-test/java/com/commercetools/project/sync/CategorySyncWithReferenceResolutionIT.java +++ b/src/integration-test/java/com/commercetools/project/sync/CategorySyncWithReferenceResolutionIT.java @@ -1,36 +1,29 @@ package com.commercetools.project.sync; +import static com.commercetools.api.models.common.LocalizedString.ofEnglish; import static com.commercetools.project.sync.util.CtpClientUtils.CTP_SOURCE_CLIENT; import static com.commercetools.project.sync.util.CtpClientUtils.CTP_TARGET_CLIENT; -import static com.commercetools.project.sync.util.IntegrationTestUtils.assertCategoryExists; -import static com.commercetools.project.sync.util.IntegrationTestUtils.cleanUpProjects; -import static com.commercetools.project.sync.util.IntegrationTestUtils.createITSyncerFactory; -import static io.sphere.sdk.models.LocalizedString.ofEnglish; +import static com.commercetools.project.sync.util.IntegrationTestUtils.*; import static java.util.Arrays.asList; -import static java.util.Collections.emptyList; -import static java.util.Collections.emptyMap; -import static java.util.Collections.singletonList; import static org.assertj.core.api.Assertions.assertThat; +import com.commercetools.api.client.ProjectApiRoot; +import com.commercetools.api.models.category.CategoryDraft; +import com.commercetools.api.models.category.CategoryDraftBuilder; +import com.commercetools.api.models.common.AssetDraft; +import com.commercetools.api.models.common.AssetDraftBuilder; +import com.commercetools.api.models.common.AssetSourceBuilder; +import com.commercetools.api.models.common.LocalizedStringBuilder; +import com.commercetools.api.models.type.CustomFieldsDraft; +import com.commercetools.api.models.type.CustomFieldsDraftBuilder; +import com.commercetools.api.models.type.FieldDefinition; +import com.commercetools.api.models.type.FieldDefinitionBuilder; +import com.commercetools.api.models.type.ResourceTypeId; +import com.commercetools.api.models.type.Type; +import com.commercetools.api.models.type.TypeDraft; +import com.commercetools.api.models.type.TypeDraftBuilder; +import com.commercetools.api.models.type.TypeTextInputHint; import com.commercetools.project.sync.category.CategorySyncer; -import io.sphere.sdk.categories.CategoryDraft; -import io.sphere.sdk.categories.CategoryDraftBuilder; -import io.sphere.sdk.categories.commands.CategoryCreateCommand; -import io.sphere.sdk.client.SphereClient; -import io.sphere.sdk.models.AssetDraft; -import io.sphere.sdk.models.AssetDraftBuilder; -import io.sphere.sdk.models.AssetSourceBuilder; -import io.sphere.sdk.models.LocalizedString; -import io.sphere.sdk.models.TextInputHint; -import io.sphere.sdk.types.CustomFieldsDraft; -import io.sphere.sdk.types.FieldDefinition; -import io.sphere.sdk.types.ResourceTypeIdsSetBuilder; -import io.sphere.sdk.types.StringFieldType; -import io.sphere.sdk.types.Type; -import io.sphere.sdk.types.TypeDraft; -import io.sphere.sdk.types.TypeDraftBuilder; -import io.sphere.sdk.types.commands.TypeCreateCommand; -import java.util.Arrays; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -52,50 +45,51 @@ void setup() { setupSourceProjectData(CTP_SOURCE_CLIENT); } - private void setupSourceProjectData(SphereClient sourceProjectClient) { - + private void setupSourceProjectData(ProjectApiRoot sourceProjectClient) { final FieldDefinition FIELD_DEFINITION = - FieldDefinition.of( - StringFieldType.of(), - "field_name", - LocalizedString.ofEnglish("label_1"), - false, - TextInputHint.SINGLE_LINE); + FieldDefinitionBuilder.of() + .type(fieldTypeBuilder -> fieldTypeBuilder.stringBuilder()) + .name("field_name") + .label(LocalizedStringBuilder.of().addValue("en", "label_1").build()) + .required(false) + .inputHint(TypeTextInputHint.SINGLE_LINE) + .build(); final TypeDraft typeDraft = - TypeDraftBuilder.of( - TYPE_KEY, - LocalizedString.ofEnglish("name_1"), - ResourceTypeIdsSetBuilder.of().addCategories().addPrices().addAssets().build()) - .description(LocalizedString.ofEnglish("description_1")) - .fieldDefinitions(Arrays.asList(FIELD_DEFINITION)) + TypeDraftBuilder.of() + .key(TYPE_KEY) + .name(ofEnglish("name_1")) + .resourceTypeIds( + ResourceTypeId.CATEGORY, ResourceTypeId.PRODUCT_PRICE, ResourceTypeId.ASSET) + .description(ofEnglish("description_1")) + .fieldDefinitions(FIELD_DEFINITION) .build(); - final Type type = - sourceProjectClient.execute(TypeCreateCommand.of(typeDraft)).toCompletableFuture().join(); + final Type type = sourceProjectClient.types().create(typeDraft).executeBlocking().getBody(); - CTP_TARGET_CLIENT.execute(TypeCreateCommand.of(typeDraft)).toCompletableFuture().join(); + CTP_TARGET_CLIENT.types().create(typeDraft).executeBlocking(); - CustomFieldsDraft customFieldsDraft = - CustomFieldsDraft.ofTypeKeyAndJson(type.getKey(), emptyMap()); + final CustomFieldsDraft customFieldsDraft = + CustomFieldsDraftBuilder.of().type(type.toResourceIdentifier()).build(); final AssetDraft assetDraft = - AssetDraftBuilder.of(emptyList(), LocalizedString.ofEnglish("assetName")) + AssetDraftBuilder.of() + .name(ofEnglish("assetName")) .key("assetKey") - .sources(singletonList(AssetSourceBuilder.ofUri("sourceUri").build())) + .sources(AssetSourceBuilder.of().uri("sourceUri").build()) .custom(customFieldsDraft) .build(); final CategoryDraft categoryDraft = - CategoryDraftBuilder.of(ofEnglish("t-shirts"), ofEnglish("t-shirts")) + CategoryDraftBuilder.of() + .name(ofEnglish("t-shirts")) + .slug(ofEnglish("t-shirts")) .key(RESOURCE_KEY) .assets(asList(assetDraft)) .custom(customFieldsDraft) .build(); - sourceProjectClient - .execute(CategoryCreateCommand.of(categoryDraft)) - .toCompletableFuture() - .join(); + + sourceProjectClient.categories().create(categoryDraft).execute().toCompletableFuture().join(); } @AfterAll diff --git a/src/integration-test/java/com/commercetools/project/sync/CliRunnerIT.java b/src/integration-test/java/com/commercetools/project/sync/CliRunnerIT.java index cf2ef8a4..e9736fdd 100644 --- a/src/integration-test/java/com/commercetools/project/sync/CliRunnerIT.java +++ b/src/integration-test/java/com/commercetools/project/sync/CliRunnerIT.java @@ -1,1127 +1,1158 @@ -package com.commercetools.project.sync; - -import static com.commercetools.project.sync.service.impl.CustomObjectServiceImpl.TIMESTAMP_GENERATOR_KEY; -import static com.commercetools.project.sync.util.CtpClientUtils.CTP_SOURCE_CLIENT; -import static com.commercetools.project.sync.util.CtpClientUtils.CTP_TARGET_CLIENT; -import static com.commercetools.project.sync.util.IntegrationTestUtils.assertCategoryExists; -import static com.commercetools.project.sync.util.IntegrationTestUtils.assertProductExists; -import static com.commercetools.project.sync.util.IntegrationTestUtils.assertProductTypeExists; -import static com.commercetools.project.sync.util.IntegrationTestUtils.cleanUpProjects; -import static com.commercetools.project.sync.util.IntegrationTestUtils.createITSyncerFactory; -import static com.commercetools.project.sync.util.QueryUtils.queryAndExecute; -import static com.commercetools.project.sync.util.SyncUtils.APPLICATION_DEFAULT_NAME; -import static com.commercetools.project.sync.util.SyncUtils.DEFAULT_RUNNER_NAME; -import static com.commercetools.project.sync.util.TestUtils.assertCartDiscountSyncerLoggingEvents; -import static com.commercetools.project.sync.util.TestUtils.assertCategorySyncerLoggingEvents; -import static com.commercetools.project.sync.util.TestUtils.assertCustomObjectSyncerLoggingEvents; -import static com.commercetools.project.sync.util.TestUtils.assertCustomerSyncerLoggingEvents; -import static com.commercetools.project.sync.util.TestUtils.assertInventoryEntrySyncerLoggingEvents; -import static com.commercetools.project.sync.util.TestUtils.assertProductSyncerLoggingEvents; -import static com.commercetools.project.sync.util.TestUtils.assertProductTypeSyncerLoggingEvents; -import static com.commercetools.project.sync.util.TestUtils.assertShoppingListSyncerLoggingEvents; -import static com.commercetools.project.sync.util.TestUtils.assertStateSyncerLoggingEvents; -import static com.commercetools.project.sync.util.TestUtils.assertTaxCategorySyncerLoggingEvents; -import static com.commercetools.project.sync.util.TestUtils.assertTypeSyncerLoggingEvents; -import static io.sphere.sdk.models.LocalizedString.ofEnglish; -import static java.lang.String.format; -import static java.util.Collections.emptyList; -import static java.util.Collections.singletonList; -import static org.assertj.core.api.Assertions.assertThat; - -import com.commercetools.project.sync.cartdiscount.CartDiscountSyncer; -import com.commercetools.project.sync.category.CategorySyncer; -import com.commercetools.project.sync.customer.CustomerSyncer; -import com.commercetools.project.sync.customobject.CustomObjectSyncer; -import com.commercetools.project.sync.inventoryentry.InventoryEntrySyncer; -import com.commercetools.project.sync.model.response.LastSyncCustomObject; -import com.commercetools.project.sync.product.ProductSyncer; -import com.commercetools.project.sync.producttype.ProductTypeSyncer; -import com.commercetools.project.sync.shoppinglist.ShoppingListSyncer; -import com.commercetools.project.sync.state.StateSyncer; -import com.commercetools.project.sync.taxcategory.TaxCategorySyncer; -import com.commercetools.project.sync.type.TypeSyncer; -import com.commercetools.sync.commons.helpers.BaseSyncStatistics; -import com.commercetools.sync.products.helpers.ProductSyncStatistics; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.JsonNodeFactory; -import com.fasterxml.jackson.databind.node.ObjectNode; -import com.neovisionaries.i18n.CountryCode; -import io.sphere.sdk.cartdiscounts.CartDiscount; -import io.sphere.sdk.cartdiscounts.CartDiscountDraft; -import io.sphere.sdk.cartdiscounts.CartDiscountDraftBuilder; -import io.sphere.sdk.cartdiscounts.CartDiscountValue; -import io.sphere.sdk.cartdiscounts.ShippingCostTarget; -import io.sphere.sdk.cartdiscounts.commands.CartDiscountCreateCommand; -import io.sphere.sdk.cartdiscounts.queries.CartDiscountQuery; -import io.sphere.sdk.categories.Category; -import io.sphere.sdk.categories.CategoryDraft; -import io.sphere.sdk.categories.CategoryDraftBuilder; -import io.sphere.sdk.categories.commands.CategoryCreateCommand; -import io.sphere.sdk.categories.queries.CategoryQuery; -import io.sphere.sdk.client.SphereClient; -import io.sphere.sdk.customers.Customer; -import io.sphere.sdk.customers.CustomerDraft; -import io.sphere.sdk.customers.CustomerDraftBuilder; -import io.sphere.sdk.customers.CustomerName; -import io.sphere.sdk.customers.CustomerSignInResult; -import io.sphere.sdk.customers.commands.CustomerCreateCommand; -import io.sphere.sdk.customers.commands.CustomerUpdateCommand; -import io.sphere.sdk.customers.commands.updateactions.ChangeName; -import io.sphere.sdk.customers.queries.CustomerQuery; -import io.sphere.sdk.customobjects.CustomObject; -import io.sphere.sdk.customobjects.CustomObjectDraft; -import io.sphere.sdk.customobjects.commands.CustomObjectUpsertCommand; -import io.sphere.sdk.customobjects.queries.CustomObjectQuery; -import io.sphere.sdk.inventory.InventoryEntry; -import io.sphere.sdk.inventory.InventoryEntryDraft; -import io.sphere.sdk.inventory.InventoryEntryDraftBuilder; -import io.sphere.sdk.inventory.commands.InventoryEntryCreateCommand; -import io.sphere.sdk.inventory.queries.InventoryEntryQuery; -import io.sphere.sdk.models.ResourceIdentifier; -import io.sphere.sdk.products.Product; -import io.sphere.sdk.products.ProductDraft; -import io.sphere.sdk.products.ProductDraftBuilder; -import io.sphere.sdk.products.ProductVariantDraftBuilder; -import io.sphere.sdk.products.commands.ProductCreateCommand; -import io.sphere.sdk.products.queries.ProductQuery; -import io.sphere.sdk.producttypes.ProductType; -import io.sphere.sdk.producttypes.ProductTypeDraft; -import io.sphere.sdk.producttypes.ProductTypeDraftBuilder; -import io.sphere.sdk.producttypes.commands.ProductTypeCreateCommand; -import io.sphere.sdk.producttypes.queries.ProductTypeQuery; -import io.sphere.sdk.queries.PagedQueryResult; -import io.sphere.sdk.queries.QueryPredicate; -import io.sphere.sdk.shoppinglists.LineItemDraft; -import io.sphere.sdk.shoppinglists.LineItemDraftBuilder; -import io.sphere.sdk.shoppinglists.ShoppingList; -import io.sphere.sdk.shoppinglists.ShoppingListDraft; -import io.sphere.sdk.shoppinglists.ShoppingListDraftBuilder; -import io.sphere.sdk.shoppinglists.commands.ShoppingListCreateCommand; -import io.sphere.sdk.shoppinglists.commands.ShoppingListDeleteCommand; -import io.sphere.sdk.shoppinglists.queries.ShoppingListQuery; -import io.sphere.sdk.states.State; -import io.sphere.sdk.states.StateDraft; -import io.sphere.sdk.states.StateDraftBuilder; -import io.sphere.sdk.states.StateType; -import io.sphere.sdk.states.commands.StateCreateCommand; -import io.sphere.sdk.states.queries.StateQuery; -import io.sphere.sdk.taxcategories.TaxCategory; -import io.sphere.sdk.taxcategories.TaxCategoryDraft; -import io.sphere.sdk.taxcategories.TaxCategoryDraftBuilder; -import io.sphere.sdk.taxcategories.TaxRateDraft; -import io.sphere.sdk.taxcategories.TaxRateDraftBuilder; -import io.sphere.sdk.taxcategories.commands.TaxCategoryCreateCommand; -import io.sphere.sdk.taxcategories.queries.TaxCategoryQuery; -import io.sphere.sdk.types.CustomFieldsDraft; -import io.sphere.sdk.types.CustomFieldsDraftBuilder; -import io.sphere.sdk.types.ResourceTypeIdsSetBuilder; -import io.sphere.sdk.types.Type; -import io.sphere.sdk.types.TypeDraft; -import io.sphere.sdk.types.TypeDraftBuilder; -import io.sphere.sdk.types.commands.TypeCreateCommand; -import io.sphere.sdk.types.queries.TypeQuery; -import java.time.ZonedDateTime; -import java.util.Collections; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; -import javax.annotation.Nonnull; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import uk.org.lidalia.slf4jext.Level; -import uk.org.lidalia.slf4jtest.TestLogger; -import uk.org.lidalia.slf4jtest.TestLoggerFactory; - -// This will suppress MoreThanOneLogger warnings in this class -@SuppressWarnings("PMD.MoreThanOneLogger") -class CliRunnerIT { - - private static final TestLogger productSyncerTestLogger = - TestLoggerFactory.getTestLogger(ProductSyncer.class); - private static final TestLogger cliRunnerTestLogger = - TestLoggerFactory.getTestLogger(CliRunner.class); - private static final TestLogger productTypeSyncerTestLogger = - TestLoggerFactory.getTestLogger(ProductTypeSyncer.class); - private static final TestLogger customerSyncerTestLogger = - TestLoggerFactory.getTestLogger(CustomerSyncer.class); - private static final TestLogger shoppingListSyncerTestLogger = - TestLoggerFactory.getTestLogger(ShoppingListSyncer.class); - private static final TestLogger stateSyncerTestLogger = - TestLoggerFactory.getTestLogger(StateSyncer.class); - private static final TestLogger inventoryEntrySyncerTestLogger = - TestLoggerFactory.getTestLogger(InventoryEntrySyncer.class); - private static final TestLogger customObjectSyncerTestLogger = - TestLoggerFactory.getTestLogger(CustomObjectSyncer.class); - private static final TestLogger typeSyncerTestLogger = - TestLoggerFactory.getTestLogger(TypeSyncer.class); - private static final TestLogger categorySyncerTestLogger = - TestLoggerFactory.getTestLogger(CategorySyncer.class); - private static final TestLogger cartDiscountSyncerTestLogger = - TestLoggerFactory.getTestLogger(CartDiscountSyncer.class); - private static final TestLogger taxCategorySyncerTestLogger = - TestLoggerFactory.getTestLogger(TaxCategorySyncer.class); - - private static final String RESOURCE_KEY = "foo"; - private static final String PROJECT_SYNC_CONTAINER_NAME = - "commercetools-project-sync.runnerName.ProductSync.timestampGenerator"; - - @BeforeEach - void setup() throws ExecutionException, InterruptedException { - cliRunnerTestLogger.clearAll(); - productSyncerTestLogger.clearAll(); - productTypeSyncerTestLogger.clearAll(); - customerSyncerTestLogger.clearAll(); - shoppingListSyncerTestLogger.clearAll(); - stateSyncerTestLogger.clearAll(); - inventoryEntrySyncerTestLogger.clearAll(); - customObjectSyncerTestLogger.clearAll(); - typeSyncerTestLogger.clearAll(); - categorySyncerTestLogger.clearAll(); - cartDiscountSyncerTestLogger.clearAll(); - taxCategorySyncerTestLogger.clearAll(); - cleanUpProjects(CTP_SOURCE_CLIENT, CTP_TARGET_CLIENT); - setupSourceProjectData(CTP_SOURCE_CLIENT); - } - - static void setupSourceProjectData(@Nonnull final SphereClient sourceProjectClient) - throws ExecutionException, InterruptedException { - final ProductTypeDraft productTypeDraft = - ProductTypeDraftBuilder.of( - RESOURCE_KEY, "sample-product-type", "a productType for t-shirts", emptyList()) - .build(); - - final ProductType productType = - sourceProjectClient - .execute(ProductTypeCreateCommand.of(productTypeDraft)) - .toCompletableFuture() - .join(); - - final TypeDraft typeDraft = - TypeDraftBuilder.of( - RESOURCE_KEY, - ofEnglish("category-custom-type"), - ResourceTypeIdsSetBuilder.of().addCategories().add("shopping-list")) - .build(); - - final StateDraft stateDraft = - StateDraftBuilder.of(RESOURCE_KEY, StateType.PRODUCT_STATE) - .roles(Collections.emptySet()) - .description(ofEnglish("State 1")) - .name(ofEnglish("State 1")) - .initial(true) - .transitions(Collections.emptySet()) - .build(); - final State state = - sourceProjectClient.execute(StateCreateCommand.of(stateDraft)).toCompletableFuture().join(); - - final CompletableFuture typeFuture = - sourceProjectClient.execute(TypeCreateCommand.of(typeDraft)).toCompletableFuture(); - - final TaxRateDraft taxRateDraft = - TaxRateDraftBuilder.of("Tax-Rate-Name-1", 0.3, false, CountryCode.DE).build(); - - final TaxCategoryDraft taxCategoryDraft = - TaxCategoryDraftBuilder.of( - "Tax-Category-Name-1", singletonList(taxRateDraft), "Tax-Category-Description-1") - .key(RESOURCE_KEY) - .build(); - - final TaxCategory taxCategory = - sourceProjectClient - .execute(TaxCategoryCreateCommand.of(taxCategoryDraft)) - .toCompletableFuture() - .join(); - - final ObjectNode customObjectValue = JsonNodeFactory.instance.objectNode().put("name", "value"); - final CustomObjectDraft customObjectDraft = - CustomObjectDraft.ofUnversionedUpsert(RESOURCE_KEY, RESOURCE_KEY, customObjectValue); - // following custom object should not be synced as it's created by the project-sync itself - final CustomObjectDraft customObjectToIgnore = - CustomObjectDraft.ofUnversionedUpsert( - PROJECT_SYNC_CONTAINER_NAME, "timestampGenerator", customObjectValue); - - final CompletableFuture> customObjectFuture1 = - sourceProjectClient - .execute(CustomObjectUpsertCommand.of(customObjectDraft)) - .toCompletableFuture(); - - final CompletableFuture> customObjectFuture2 = - sourceProjectClient - .execute(CustomObjectUpsertCommand.of(customObjectToIgnore)) - .toCompletableFuture(); - - final CategoryDraft categoryDraft = - CategoryDraftBuilder.of(ofEnglish("t-shirts"), ofEnglish("t-shirts")) - .key(RESOURCE_KEY) - .build(); - - final CompletableFuture categoryFuture = - sourceProjectClient.execute(CategoryCreateCommand.of(categoryDraft)).toCompletableFuture(); - - final CustomerDraft customerDraft = - CustomerDraftBuilder.of("test@email.com", "testPassword").key(RESOURCE_KEY).build(); - - final CompletableFuture customerFuture = - sourceProjectClient.execute(CustomerCreateCommand.of(customerDraft)).toCompletableFuture(); - - CompletableFuture.allOf( - typeFuture, customObjectFuture1, customObjectFuture2, categoryFuture, customerFuture) - .join(); - - final ProductDraft productDraft = - ProductDraftBuilder.of( - productType, - ofEnglish("V-neck Tee"), - ofEnglish("v-neck-tee"), - ProductVariantDraftBuilder.of().key(RESOURCE_KEY).sku(RESOURCE_KEY).build()) - .state(state) - .taxCategory(taxCategory) - .key(RESOURCE_KEY) - .publish(true) - .build(); - - final CompletableFuture productFuture = - sourceProjectClient.execute(ProductCreateCommand.of(productDraft)).toCompletableFuture(); - - final InventoryEntryDraft inventoryEntryDraft = - InventoryEntryDraftBuilder.of(RESOURCE_KEY, 1L).build(); - - final CompletableFuture inventoryFuture = - sourceProjectClient - .execute(InventoryEntryCreateCommand.of(inventoryEntryDraft)) - .toCompletableFuture(); - - final CartDiscountDraft cartDiscountDraft = - CartDiscountDraftBuilder.of( - ofEnglish("my-cart-discount"), - "1 = 1", - CartDiscountValue.ofRelative(1), - ShippingCostTarget.of(), - "0.1", - true) - .key(RESOURCE_KEY) - .build(); - - final CompletableFuture cartDiscountFuture = - sourceProjectClient - .execute(CartDiscountCreateCommand.of(cartDiscountDraft)) - .toCompletableFuture(); - CompletableFuture.allOf(productFuture, inventoryFuture, cartDiscountFuture); - - final CustomerSignInResult customerSignInResult = customerFuture.get(); - final Product product = productFuture.get(); - final LineItemDraft lineItemDraft = LineItemDraftBuilder.of(product.getId()).build(); - final CustomFieldsDraft customFieldsDraft = - CustomFieldsDraftBuilder.ofTypeId(typeFuture.get().getId()).build(); - - final ShoppingListDraft shoppingListDraft = - ShoppingListDraftBuilder.of(ofEnglish("shoppingList-name")) - .key(RESOURCE_KEY) - .customer(ResourceIdentifier.ofId(customerSignInResult.getCustomer().getId())) - .lineItems(Collections.singletonList(lineItemDraft)) - .custom(customFieldsDraft) - .build(); - - sourceProjectClient - .execute(ShoppingListCreateCommand.of(shoppingListDraft)) - .toCompletableFuture() - .join(); - } - - @AfterAll - static void tearDownSuite() { - cleanUpProjects(CTP_SOURCE_CLIENT, CTP_TARGET_CLIENT); - } - - @Test - void run_WithSyncAsArgumentWithAllArg_ShouldExecuteAllSyncers() { - // test - CliRunner.of().run(new String[] {"-s", "all"}, createITSyncerFactory()); - - // assertions - assertAllSyncersLoggingEvents(1); - - assertAllResourcesAreSyncedToTarget(CTP_TARGET_CLIENT); - } - - @Test - void run_WithSyncAsArgumentWhenAllArgumentsPassed_ShouldExecuteAllSyncers() { - // test - CliRunner.of() - .run( - new String[] { - "-s", - "types", - "productTypes", - "customers", - "customObjects", - "taxCategories", - "categories", - "inventoryEntries", - "cartDiscounts", - "states", - "products", - "shoppingLists" - }, - createITSyncerFactory()); - - // assertions - assertAllSyncersLoggingEvents(1); - - assertAllResourcesAreSyncedToTarget(CTP_TARGET_CLIENT); - } - - @Test - void run_WithSyncAsArgumentWithCustomersAndShoppingLists_ShouldExecuteGivenSyncers() { - prepareDataForShoppingListSync(CTP_SOURCE_CLIENT); - - // test - CliRunner.of().run(new String[] {"-s", "customers", "shoppingLists"}, createITSyncerFactory()); - - // assertions - assertCustomerSyncerLoggingEvents(customerSyncerTestLogger, 1); - assertShoppingListSyncerLoggingEvents(shoppingListSyncerTestLogger, 1); - - assertCustomersAreSyncedCorrectly(CTP_TARGET_CLIENT); - assertShoppingListsAreSyncedCorrectly(CTP_TARGET_CLIENT); - - final String sourceProjectKey = CTP_SOURCE_CLIENT.getConfig().getProjectKey(); - - assertLastSyncCustomObjectExists( - CTP_TARGET_CLIENT, sourceProjectKey, "customerSync", "runnerName"); - assertLastSyncCustomObjectExists( - CTP_TARGET_CLIENT, sourceProjectKey, "shoppingListSync", "runnerName"); - } - - @Test - void - run_WithSyncAsArgumentWithCategoriesTaxCategoriesAndCartDiscounts_ShouldExecuteGivenSyncers() { - // test - CliRunner.of() - .run( - new String[] {"-s", "taxCategories", "categories", "cartDiscounts"}, - createITSyncerFactory()); - // assertions - assertCategorySyncerLoggingEvents(categorySyncerTestLogger, 1); - assertTaxCategorySyncerLoggingEvents(taxCategorySyncerTestLogger, 1); - assertCartDiscountSyncerLoggingEvents(cartDiscountSyncerTestLogger, 1); - - assertCategoriesAreSyncedCorrectly(CTP_TARGET_CLIENT); - assertTaxCategoriesAreSyncedCorrectly(CTP_TARGET_CLIENT); - assertCartDiscountsAreSyncedCorrectly(CTP_TARGET_CLIENT); - - final String sourceProjectKey = CTP_SOURCE_CLIENT.getConfig().getProjectKey(); - - assertLastSyncCustomObjectExists( - CTP_TARGET_CLIENT, sourceProjectKey, "categorySync", "runnerName"); - assertLastSyncCustomObjectExists( - CTP_TARGET_CLIENT, sourceProjectKey, "taxCategorySync", "runnerName"); - assertLastSyncCustomObjectExists( - CTP_TARGET_CLIENT, sourceProjectKey, "cartDiscountSync", "runnerName"); - } - - @Test - void - run_WithSyncAsArgumentWithProductTypesCategoriesAndShoppingLists_ShouldExecuteGivenSyncers() { - // preparation - prepareDataForShoppingListSync(CTP_SOURCE_CLIENT); - - // test - CliRunner.of() - .run( - new String[] {"-s", "productTypes", "categories", "shoppingLists"}, - createITSyncerFactory()); - // assertions - assertProductTypeSyncerLoggingEvents(productTypeSyncerTestLogger, 1); - assertCategorySyncerLoggingEvents(categorySyncerTestLogger, 1); - assertShoppingListSyncerLoggingEvents(shoppingListSyncerTestLogger, 1); - - assertProductTypesAreSyncedCorrectly(CTP_TARGET_CLIENT); - assertCategoriesAreSyncedCorrectly(CTP_TARGET_CLIENT); - assertShoppingListsAreSyncedCorrectly(CTP_TARGET_CLIENT); - - final String sourceProjectKey = CTP_SOURCE_CLIENT.getConfig().getProjectKey(); - - assertLastSyncCustomObjectExists( - CTP_TARGET_CLIENT, sourceProjectKey, "categorySync", "runnerName"); - assertLastSyncCustomObjectExists( - CTP_TARGET_CLIENT, sourceProjectKey, "productTypeSync", "runnerName"); - assertLastSyncCustomObjectExists( - CTP_TARGET_CLIENT, sourceProjectKey, "shoppingListSync", "runnerName"); - } - - @Test - void - run_WithSyncAsArgumentWithProductsAndShoppingListsAlongWithTheirReferencedResources_ShouldExecuteGivenSyncers() { - // test - CliRunner.of() - .run( - new String[] { - "-s", - "types", - "productTypes", - "states", - "taxCategories", - "products", - "customers", - "shoppingLists" - }, - createITSyncerFactory()); - // assertions - assertProductSyncerLoggingEvents(productSyncerTestLogger, 1); - - assertTypesAreSyncedCorrectly(CTP_TARGET_CLIENT); - assertProductsAreSyncedCorrectly(CTP_TARGET_CLIENT); - assertProductTypesAreSyncedCorrectly(CTP_TARGET_CLIENT); - assertStatesAreSyncedCorrectly(CTP_TARGET_CLIENT); - assertTaxCategoriesAreSyncedCorrectly(CTP_TARGET_CLIENT); - assertCustomersAreSyncedCorrectly(CTP_TARGET_CLIENT); - assertShoppingListsAreSyncedCorrectly(CTP_TARGET_CLIENT); - - final String sourceProjectKey = CTP_SOURCE_CLIENT.getConfig().getProjectKey(); - - assertLastSyncCustomObjectExists(CTP_TARGET_CLIENT, sourceProjectKey, "typeSync", "runnerName"); - assertLastSyncCustomObjectExists( - CTP_TARGET_CLIENT, sourceProjectKey, "productSync", "runnerName"); - assertLastSyncCustomObjectExists( - CTP_TARGET_CLIENT, sourceProjectKey, "productTypeSync", "runnerName"); - assertLastSyncCustomObjectExists( - CTP_TARGET_CLIENT, sourceProjectKey, "stateSync", "runnerName"); - assertLastSyncCustomObjectExists( - CTP_TARGET_CLIENT, sourceProjectKey, "taxCategorySync", "runnerName"); - assertLastSyncCustomObjectExists( - CTP_TARGET_CLIENT, sourceProjectKey, "customerSync", "runnerName"); - assertLastSyncCustomObjectExists( - CTP_TARGET_CLIENT, sourceProjectKey, "shoppingListSync", "runnerName"); - } - - @Test - void - run_WithCustomerSyncAsArgument_ShouldSyncCustomersAndStoreLastSyncTimestampsAsCustomObject() { - // test - CliRunner.of().run(new String[] {"-s", "customers"}, createITSyncerFactory()); - // assertions - assertThat(customerSyncerTestLogger.getAllLoggingEvents()).hasSize(2); - - assertCustomerSyncerLoggingEvents(customerSyncerTestLogger, 1); - - assertCustomersAreSyncedCorrectly(CTP_TARGET_CLIENT); - - final String sourceProjectKey = CTP_SOURCE_CLIENT.getConfig().getProjectKey(); - - assertLastSyncCustomObjectExists( - CTP_TARGET_CLIENT, sourceProjectKey, "customerSync", "runnerName"); - } - - @Test - void run_WithUpdatedCustomer_ShouldSyncCustomersAndStoreLastSyncTimestampsAsCustomObject() { - ZonedDateTime lastModifiedTime = null; - // preparation - final SyncerFactory syncerFactory = createITSyncerFactory(); - - // test - CliRunner.of().run(new String[] {"-s", "customers"}, syncerFactory); - - lastModifiedTime = - getCustomObjectLastModifiedTime(CTP_TARGET_CLIENT, "customerSync", "runnerName"); - updateCustomerSourceObject(CTP_SOURCE_CLIENT); - - // test - CliRunner.of().run(new String[] {"-s", "customers"}, syncerFactory); - - assertUpdatedCustomersAreSyncedCorrectly(CTP_SOURCE_CLIENT, CTP_TARGET_CLIENT); - - assertUpdatedCustomObjectTimestampAfterSync( - CTP_TARGET_CLIENT, "customerSync", "runnerName", lastModifiedTime); - } - - private void assertUpdatedCustomObjectTimestampAfterSync( - @Nonnull final SphereClient targetClient, - @Nonnull final String syncModuleName, - @Nonnull final String runnerName, - @Nonnull final ZonedDateTime lastModifiedTime) { - final PagedQueryResult> lastSyncResult = - fetchLastSyncCustomObject(targetClient, syncModuleName, runnerName); - - assertThat(lastModifiedTime) - .isBefore(lastSyncResult.getResults().get(0).getValue().getLastSyncTimestamp()); - } - - private ZonedDateTime getCustomObjectLastModifiedTime( - @Nonnull final SphereClient targetClient, - @Nonnull final String syncModuleName, - @Nonnull final String runnerName) { - final PagedQueryResult> lastSyncResult = - fetchLastSyncCustomObject(targetClient, syncModuleName, runnerName); - - return lastSyncResult.getResults().get(0).getValue().getLastSyncTimestamp(); - } - - private void updateCustomerSourceObject(@Nonnull final SphereClient sourceProjectClient) { - final PagedQueryResult customerPagedQueryResult = - sourceProjectClient - .execute( - CustomerQuery.of() - .withPredicates(QueryPredicate.of(format("key=\"%s\"", RESOURCE_KEY)))) - .toCompletableFuture() - .join(); - final Customer customer = customerPagedQueryResult.getResults().get(0); - - sourceProjectClient - .execute( - CustomerUpdateCommand.of( - customer, - ChangeName.of(CustomerName.ofFirstAndLastName("testFirstName", "testLastName")))) - .toCompletableFuture() - .join(); - } - - private void assertUpdatedCustomersAreSyncedCorrectly( - @Nonnull final SphereClient cspClient, @Nonnull final SphereClient ctpClient) { - final PagedQueryResult sourceCustomerPagedQueryResult = - cspClient - .execute( - CustomerQuery.of() - .withPredicates(QueryPredicate.of(format("key=\"%s\"", RESOURCE_KEY)))) - .toCompletableFuture() - .join(); - Customer sourceCustomer = sourceCustomerPagedQueryResult.getResults().get(0); - - final PagedQueryResult targetCustomerPagedQueryResult = - ctpClient - .execute( - CustomerQuery.of() - .withPredicates(QueryPredicate.of(format("key=\"%s\"", RESOURCE_KEY)))) - .toCompletableFuture() - .join(); - Customer targetCustomer = targetCustomerPagedQueryResult.getResults().get(0); - - assertThat(sourceCustomer.getName()).isEqualTo(targetCustomer.getName()); - } - - @Test - void - run_WithShoppingListSyncAsArgument_ShouldSyncShoppingListsAndStoreLastSyncTimestampsAsCustomObject() { - // preparation - // Shopping List contains Product, Customer and Type references. So, here it is recreating - // ShoppingList without any references. - prepareDataForShoppingListSync(CTP_SOURCE_CLIENT); - - // test - CliRunner.of().run(new String[] {"-s", "shoppingLists"}, createITSyncerFactory()); - - // create clients again (for assertions and cleanup), since the run method closes the clients - // after execution is done. - // assertions - assertThat(shoppingListSyncerTestLogger.getAllLoggingEvents()).hasSize(2); - - assertShoppingListSyncerLoggingEvents(shoppingListSyncerTestLogger, 1); - - assertShoppingListsAreSyncedCorrectly(CTP_TARGET_CLIENT); - - final String sourceProjectKey = CTP_SOURCE_CLIENT.getConfig().getProjectKey(); - - assertLastSyncCustomObjectExists( - CTP_TARGET_CLIENT, sourceProjectKey, "shoppingListSync", "runnerName"); - } - - private void prepareDataForShoppingListSync(SphereClient sourceClient) { - queryAndExecute(sourceClient, ShoppingListQuery.of(), ShoppingListDeleteCommand::of).join(); - final ShoppingListDraft shoppingListDraft = - ShoppingListDraftBuilder.of(ofEnglish("shoppingList-name")).key(RESOURCE_KEY).build(); - - sourceClient - .execute(ShoppingListCreateCommand.of(shoppingListDraft)) - .toCompletableFuture() - .join(); - } - - @Test - void - run_WithCustomObjectSyncAsArgument_ShouldSyncCustomObjectsWithoutProjectSyncGeneratedCustomObjects() { - // test - CliRunner.of().run(new String[] {"-s", "customObjects"}, createITSyncerFactory()); - // assertions - // assertions - assertThat(customObjectSyncerTestLogger.getAllLoggingEvents()).hasSize(2); - - assertCustomObjectSyncerLoggingEvents(customObjectSyncerTestLogger, 1); - } - - @Test - void - run_WithProductTypeSyncAsArgument_ShouldExecuteProductTypeSyncerAndStoreLastSyncTimestampsAsCustomObject() { - // test - CliRunner.of().run(new String[] {"-s", "productTypes"}, createITSyncerFactory()); - // assertions - assertThat(productTypeSyncerTestLogger.getAllLoggingEvents()).hasSize(2); - - assertProductTypeSyncerLoggingEvents(productTypeSyncerTestLogger, 1); - - assertProductTypesAreSyncedCorrectly(CTP_TARGET_CLIENT); - - final ZonedDateTime lastSyncTimestamp = - assertCurrentCtpTimestampGeneratorAndGetLastModifiedAt( - CTP_TARGET_CLIENT, DEFAULT_RUNNER_NAME, "ProductTypeSync"); - - final String sourceProjectKey = CTP_SOURCE_CLIENT.getConfig().getProjectKey(); - - assertLastSyncCustomObjectIsCorrect( - CTP_TARGET_CLIENT, - sourceProjectKey, - "productTypeSync", - DEFAULT_RUNNER_NAME, - ProductSyncStatistics.class, - lastSyncTimestamp); - } - - private static void assertTypesAreSyncedCorrectly(@Nonnull final SphereClient ctpClient) { - final String queryPredicate = format("key=\"%s\"", RESOURCE_KEY); - - final PagedQueryResult typeQueryResult = - ctpClient - .execute(TypeQuery.of().withPredicates(QueryPredicate.of(queryPredicate))) - .toCompletableFuture() - .join(); - - assertThat(typeQueryResult.getResults()) - .hasSize(1) - .singleElement() - .satisfies(productType -> assertThat(productType.getKey()).isEqualTo(RESOURCE_KEY)); - } - - private static void assertProductTypesAreSyncedCorrectly(@Nonnull final SphereClient ctpClient) { - - final PagedQueryResult productTypeQueryResult = - ctpClient.execute(ProductTypeQuery.of().byKey(RESOURCE_KEY)).toCompletableFuture().join(); - - assertThat(productTypeQueryResult.getResults()) - .hasSize(1) - .singleElement() - .satisfies(productType -> assertThat(productType.getKey()).isEqualTo(RESOURCE_KEY)); - } - - private static void assertProductsAreSyncedCorrectly(@Nonnull final SphereClient ctpClient) { - - final PagedQueryResult productQueryResult = - ctpClient.execute(ProductQuery.of()).toCompletableFuture().join(); - - assertThat(productQueryResult.getResults()) - .hasSize(1) - .singleElement() - .satisfies(product -> assertThat(product.getKey()).isEqualTo(RESOURCE_KEY)); - } - - private static void assertCustomersAreSyncedCorrectly(@Nonnull final SphereClient ctpClient) { - final PagedQueryResult customerPagedQueryResult = - ctpClient - .execute( - CustomerQuery.of() - .withPredicates(QueryPredicate.of(format("key=\"%s\"", RESOURCE_KEY)))) - .toCompletableFuture() - .join(); - assertThat(customerPagedQueryResult.getResults()).hasSize(1); - } - - private static void assertShoppingListsAreSyncedCorrectly(@Nonnull final SphereClient ctpClient) { - final PagedQueryResult shoppingListPagedQueryResult = - ctpClient - .execute( - ShoppingListQuery.of() - .withPredicates(QueryPredicate.of(format("key=\"%s\"", RESOURCE_KEY)))) - .toCompletableFuture() - .join(); - assertThat(shoppingListPagedQueryResult.getResults()).hasSize(1); - } - - private static void assertCategoriesAreSyncedCorrectly(@Nonnull final SphereClient ctpClient) { - final PagedQueryResult categoryPagedQueryResult = - ctpClient - .execute( - CategoryQuery.of() - .withPredicates(QueryPredicate.of(format("key=\"%s\"", RESOURCE_KEY)))) - .toCompletableFuture() - .join(); - assertThat(categoryPagedQueryResult.getResults()).hasSize(1); - } - - private static void assertStatesAreSyncedCorrectly(@Nonnull final SphereClient ctpClient) { - final PagedQueryResult statePagedQueryResult = - ctpClient - .execute( - StateQuery.of() - .withPredicates(QueryPredicate.of(format("key=\"%s\"", RESOURCE_KEY)))) - .toCompletableFuture() - .join(); - assertThat(statePagedQueryResult.getResults()).hasSize(1); - } - - private static void assertTaxCategoriesAreSyncedCorrectly(@Nonnull final SphereClient ctpClient) { - final PagedQueryResult taxCategoryPagedQueryResult = - ctpClient - .execute( - TaxCategoryQuery.of() - .withPredicates(QueryPredicate.of(format("key=\"%s\"", RESOURCE_KEY)))) - .toCompletableFuture() - .join(); - assertThat(taxCategoryPagedQueryResult.getResults()).hasSize(1); - } - - private static void assertCartDiscountsAreSyncedCorrectly(@Nonnull final SphereClient ctpClient) { - final PagedQueryResult cartDiscountPagedQueryResult = - ctpClient - .execute( - CartDiscountQuery.of() - .withPredicates(QueryPredicate.of(format("key=\"%s\"", RESOURCE_KEY)))) - .toCompletableFuture() - .join(); - assertThat(cartDiscountPagedQueryResult.getResults()).hasSize(1); - } - - private void assertLastSyncCustomObjectIsCorrect( - @Nonnull final SphereClient targetClient, - @Nonnull final String sourceProjectKey, - @Nonnull final String syncModuleName, - @Nonnull final String syncRunnerName, - @Nonnull final Class statisticsClass, - @Nonnull final ZonedDateTime lastSyncTimestamp) { - - final PagedQueryResult> lastSyncResult = - fetchLastSyncCustomObject(targetClient, syncModuleName, syncRunnerName); - - assertThat(lastSyncResult.getResults()) - .hasSize(1) - .singleElement() - .satisfies( - lastSyncCustomObject -> { - assertThat(lastSyncCustomObject.getKey()).isEqualTo(sourceProjectKey); - assertThat(lastSyncCustomObject.getValue()) - .satisfies( - value -> { - // Excluding til BaseStatisticsDeserializer works with correct type. - // assertThat(value.getLastSyncStatistics()).isInstanceOf(statisticsClass); - assertThat(value.getLastSyncStatistics().getProcessed().get()).isEqualTo(1); - assertThat(value.getLastSyncTimestamp()) - .isBeforeOrEqualTo(lastSyncTimestamp); - }); - }); - } - - @Nonnull - private ZonedDateTime assertCurrentCtpTimestampGeneratorAndGetLastModifiedAt( - @Nonnull final SphereClient targetClient, - @Nonnull final String runnerName, - @Nonnull final String syncModuleName) { - - final CustomObjectQuery timestampGeneratorQuery = - CustomObjectQuery.of(String.class) - .byContainer( - format( - "%s.%s.%s.%s", - APPLICATION_DEFAULT_NAME, runnerName, syncModuleName, TIMESTAMP_GENERATOR_KEY)); - - final PagedQueryResult> currentCtpTimestampGeneratorResults = - targetClient.execute(timestampGeneratorQuery).toCompletableFuture().join(); - - assertThat(currentCtpTimestampGeneratorResults.getResults()) - .hasSize(1) - .singleElement() - .satisfies( - currentCtpTimestamp -> { - assertThat(currentCtpTimestamp.getKey()).isEqualTo(TIMESTAMP_GENERATOR_KEY); - assertThat(currentCtpTimestamp.getValue()) - .matches( - "[0-9a-fA-F]{8}\\-[0-9a-fA-F]{4}\\-[0-9a-fA-F]{4}\\-[0-9a-fA-F]{4}\\-[0-9a-fA-F]{12}"); - }); - - return currentCtpTimestampGeneratorResults.getResults().get(0).getLastModifiedAt(); - } - - @Test - void - run_WithSyncAsArgumentWithAllArgAsDeltaSync_ShouldExecuteAllSyncersAndStoreLastSyncTimestampsAsCustomObjects() { - // test - CliRunner.of().run(new String[] {"-s", "all", "-r", "runnerName"}, createITSyncerFactory()); - assertAllSyncersLoggingEvents(1); - - assertAllResourcesAreSyncedToTarget(CTP_TARGET_CLIENT); - assertCurrentCtpTimestampGeneratorAndGetLastModifiedAt( - CTP_TARGET_CLIENT, "runnerName", "ProductTypeSync"); - - final String sourceProjectKey = CTP_SOURCE_CLIENT.getConfig().getProjectKey(); - - assertLastSyncCustomObjectExists( - CTP_TARGET_CLIENT, sourceProjectKey, "productSync", "runnerName"); - - assertLastSyncCustomObjectExists( - CTP_TARGET_CLIENT, sourceProjectKey, "categorySync", "runnerName"); - - assertLastSyncCustomObjectExists( - CTP_TARGET_CLIENT, sourceProjectKey, "productTypeSync", "runnerName"); - - assertLastSyncCustomObjectExists(CTP_TARGET_CLIENT, sourceProjectKey, "typeSync", "runnerName"); - - assertLastSyncCustomObjectExists( - CTP_TARGET_CLIENT, sourceProjectKey, "inventorySync", "runnerName"); - - assertLastSyncCustomObjectExists( - CTP_TARGET_CLIENT, sourceProjectKey, "cartDiscountSync", "runnerName"); - - assertLastSyncCustomObjectExists( - CTP_TARGET_CLIENT, sourceProjectKey, "stateSync", "runnerName"); - - assertLastSyncCustomObjectExists( - CTP_TARGET_CLIENT, sourceProjectKey, "taxCategorySync", "runnerName"); - - assertLastSyncCustomObjectExists( - CTP_TARGET_CLIENT, sourceProjectKey, "customObjectSync", "runnerName"); - - assertLastSyncCustomObjectExists( - CTP_TARGET_CLIENT, sourceProjectKey, "customerSync", "runnerName"); - } - - @Test - void run_WithSyncAsArgumentWithAllArgAsFullSync_ShouldExecuteAllSyncers() { - // test - CliRunner.of() - .run(new String[] {"-s", "all", "-r", "runnerName", "-f"}, createITSyncerFactory()); - // assertions - assertAllSyncersLoggingEvents(1); - - assertAllResourcesAreSyncedToTarget(CTP_TARGET_CLIENT); - assertCurrentCtpTimestampGeneratorDoesntExist( - CTP_TARGET_CLIENT, "runnerName", "ProductTypeSync"); - assertNoProjectSyncCustomObjectExists(CTP_TARGET_CLIENT); - } - - @Test - void - run_WithSyncAsArgumentWithAllArgAsFullSyncAndWithCustomQueryAndLimitForProducts_ShouldExecuteAllSyncers() { - final Long limit = 100L; - final String customQuery = "\"published=true AND masterVariant(key= \\\"foo\\\")\""; - final String productQueryParametersValue = - "{\"limit\": " + limit + ", \"where\": " + customQuery + "}"; - - // test - CliRunner.of() - .run( - new String[] { - "-s", - "all", - "-r", - "runnerName", - "-f", - "-productQueryParameters", - productQueryParametersValue - }, - createITSyncerFactory()); - // assertions - assertAllSyncersLoggingEvents(1); - - assertAllResourcesAreSyncedToTarget(CTP_TARGET_CLIENT); - assertCurrentCtpTimestampGeneratorDoesntExist( - CTP_TARGET_CLIENT, "runnerName", "ProductTypeSync"); - assertNoProjectSyncCustomObjectExists(CTP_TARGET_CLIENT); - } - - private void assertNoProjectSyncCustomObjectExists(@Nonnull final SphereClient targetClient) { - final CustomObjectQuery lastSyncQuery = - CustomObjectQuery.of(LastSyncCustomObject.class) - .plusPredicates( - customObjectQueryModel -> - customObjectQueryModel.container().is(PROJECT_SYNC_CONTAINER_NAME)); - final PagedQueryResult> lastSyncResult = - targetClient.execute(lastSyncQuery).toCompletableFuture().join(); - assertThat(lastSyncResult.getResults()).isEmpty(); - } - - private void assertCurrentCtpTimestampGeneratorDoesntExist( - @Nonnull final SphereClient targetClient, - @Nonnull final String runnerName, - @Nonnull final String syncModuleName) { - - final CustomObjectQuery timestampGeneratorQuery = - CustomObjectQuery.of(String.class) - .byContainer( - format( - "commercetools-project-sync.%s.%s.%s", - runnerName, syncModuleName, TIMESTAMP_GENERATOR_KEY)); - - final PagedQueryResult> currentCtpTimestampGeneratorResults = - targetClient.execute(timestampGeneratorQuery).toCompletableFuture().join(); - - assertThat(currentCtpTimestampGeneratorResults.getResults()).isEmpty(); - } - - private void assertLastSyncCustomObjectExists( - @Nonnull final SphereClient targetClient, - @Nonnull final String sourceProjectKey, - @Nonnull final String syncModuleName, - @Nonnull final String runnerName) { - - final PagedQueryResult> lastSyncResult = - fetchLastSyncCustomObject(targetClient, syncModuleName, runnerName); - - assertThat(lastSyncResult.getResults()) - .hasSize(1) - .singleElement() - .satisfies( - lastSyncCustomObject -> { - assertThat(lastSyncCustomObject.getKey()).isEqualTo(sourceProjectKey); - assertThat(lastSyncCustomObject.getValue()) - .satisfies( - value -> { - assertThat(value.getLastSyncTimestamp()).isNotNull(); - assertThat(value.getLastSyncDurationInMillis()).isNotNull(); - assertThat(value.getApplicationVersion()).isNotNull(); - }); - }); - } - - private PagedQueryResult> fetchLastSyncCustomObject( - @Nonnull SphereClient targetClient, - @Nonnull String syncModuleName, - @Nonnull String runnerName) { - final CustomObjectQuery lastSyncQuery = - CustomObjectQuery.of(LastSyncCustomObject.class) - .byContainer(format("%s.%s.%s", APPLICATION_DEFAULT_NAME, runnerName, syncModuleName)); - - return targetClient.execute(lastSyncQuery).toCompletableFuture().join(); - } - - private static void assertAllResourcesAreSyncedToTarget( - @Nonnull final SphereClient targetClient) { - - assertProductTypeExists(targetClient, RESOURCE_KEY); - assertCategoryExists(targetClient, RESOURCE_KEY); - assertProductExists(targetClient, RESOURCE_KEY, RESOURCE_KEY, RESOURCE_KEY); - - final String queryPredicate = format("key=\"%s\"", RESOURCE_KEY); - - final PagedQueryResult typeQueryResult = - targetClient - .execute(TypeQuery.of().withPredicates(QueryPredicate.of(queryPredicate))) - .toCompletableFuture() - .join(); - - assertThat(typeQueryResult.getResults()) - .hasSize(1) - .singleElement() - .satisfies(type -> assertThat(type.getKey()).isEqualTo(RESOURCE_KEY)); - - final PagedQueryResult taxCategoryQueryResult = - targetClient - .execute(TaxCategoryQuery.of().withPredicates(QueryPredicate.of(queryPredicate))) - .toCompletableFuture() - .join(); - - assertThat(taxCategoryQueryResult.getResults()) - .hasSize(1) - .singleElement() - .satisfies(taxCategory -> assertThat(taxCategory.getKey()).isEqualTo(RESOURCE_KEY)); - - final PagedQueryResult inventoryEntryQueryResult = - targetClient - .execute( - InventoryEntryQuery.of() - .withPredicates(QueryPredicate.of(format("sku=\"%s\"", RESOURCE_KEY)))) - .toCompletableFuture() - .join(); - - assertThat(inventoryEntryQueryResult.getResults()) - .hasSize(1) - .singleElement() - .satisfies(inventoryEntry -> assertThat(inventoryEntry.getSku()).isEqualTo(RESOURCE_KEY)); - - final PagedQueryResult cartDiscountPagedQueryResult = - targetClient - .execute( - CartDiscountQuery.of() - .withPredicates(queryModel -> queryModel.key().is(RESOURCE_KEY))) - .toCompletableFuture() - .join(); - - assertThat(cartDiscountPagedQueryResult.getResults()) - .hasSize(1) - .singleElement() - .satisfies(cartDiscount -> assertThat(cartDiscount.getKey()).isEqualTo(RESOURCE_KEY)); - - final PagedQueryResult statePagedQueryResult = - targetClient - .execute( - StateQuery.of().withPredicates(queryModel -> queryModel.key().is(RESOURCE_KEY))) - .toCompletableFuture() - .join(); - - assertThat(statePagedQueryResult.getResults()) - .hasSize(1) - .singleElement() - .satisfies(state -> assertThat(state.getKey()).isEqualTo(RESOURCE_KEY)); - - final PagedQueryResult> customObjectPagedQueryResult = - targetClient - .execute( - CustomObjectQuery.ofJsonNode() - .withPredicates( - queryModel -> - queryModel - .key() - .is(RESOURCE_KEY) - .and(queryModel.container().is(RESOURCE_KEY)))) - .toCompletableFuture() - .join(); - - assertThat(customObjectPagedQueryResult.getResults()) - .hasSize(1) - .singleElement() - .satisfies(customObject -> assertThat(customObject.getKey()).isEqualTo(RESOURCE_KEY)); - - final PagedQueryResult customerPagedQueryResult = - targetClient - .execute( - CustomerQuery.of().withPredicates(queryModel -> queryModel.key().is(RESOURCE_KEY))) - .toCompletableFuture() - .join(); - assertThat(customerPagedQueryResult.getResults()).hasSize(1); - - final PagedQueryResult shoppingListPagedQueryResult = - targetClient - .execute( - ShoppingListQuery.of() - .withPredicates(queryModel -> queryModel.key().is(RESOURCE_KEY))) - .toCompletableFuture() - .join(); - assertThat(shoppingListPagedQueryResult.getResults()).hasSize(1); - } - - public static void assertAllSyncersLoggingEvents(final int numberOfResources) { - - assertThat(cliRunnerTestLogger.getAllLoggingEvents()) - .allMatch(loggingEvent -> !Level.ERROR.equals(loggingEvent.getLevel())); - - assertTypeSyncerLoggingEvents(typeSyncerTestLogger, numberOfResources); - assertProductTypeSyncerLoggingEvents(productTypeSyncerTestLogger, numberOfResources); - assertCategorySyncerLoggingEvents(categorySyncerTestLogger, numberOfResources); - assertProductSyncerLoggingEvents(productSyncerTestLogger, numberOfResources); - assertInventoryEntrySyncerLoggingEvents(inventoryEntrySyncerTestLogger, numberOfResources); - assertCartDiscountSyncerLoggingEvents(cartDiscountSyncerTestLogger, numberOfResources); - // +1 state is a built-in state and it cant be deleted - assertStateSyncerLoggingEvents(stateSyncerTestLogger, numberOfResources + 1); - assertTaxCategorySyncerLoggingEvents(taxCategorySyncerTestLogger, numberOfResources); - assertCustomerSyncerLoggingEvents(customerSyncerTestLogger, numberOfResources); - assertShoppingListSyncerLoggingEvents(shoppingListSyncerTestLogger, numberOfResources); - - // Every sync module is expected to have 2 logs (start and stats summary) - assertThat(typeSyncerTestLogger.getAllLoggingEvents()).hasSize(2); - assertThat(productTypeSyncerTestLogger.getAllLoggingEvents()).hasSize(2); - assertThat(categorySyncerTestLogger.getAllLoggingEvents()).hasSize(2); - assertThat(productSyncerTestLogger.getAllLoggingEvents()).hasSize(2); - assertThat(inventoryEntrySyncerTestLogger.getAllLoggingEvents()).hasSize(2); - assertThat(cartDiscountSyncerTestLogger.getAllLoggingEvents()).hasSize(2); - assertThat(stateSyncerTestLogger.getAllLoggingEvents()).hasSize(2); - assertThat(taxCategorySyncerTestLogger.getAllLoggingEvents()).hasSize(2); - assertThat(customObjectSyncerTestLogger.getAllLoggingEvents()).hasSize(2); - assertThat(customerSyncerTestLogger.getAllLoggingEvents()).hasSize(2); - assertThat(shoppingListSyncerTestLogger.getAllLoggingEvents()).hasSize(2); - } -} +// package com.commercetools.project.sync; +// +// import static +// com.commercetools.project.sync.service.impl.CustomObjectServiceImpl.TIMESTAMP_GENERATOR_KEY; +// import static com.commercetools.project.sync.util.CtpClientUtils.CTP_SOURCE_CLIENT; +// import static com.commercetools.project.sync.util.CtpClientUtils.CTP_TARGET_CLIENT; +// import static com.commercetools.project.sync.util.IntegrationTestUtils.assertCategoryExists; +// import static com.commercetools.project.sync.util.IntegrationTestUtils.assertProductExists; +// import static com.commercetools.project.sync.util.IntegrationTestUtils.assertProductTypeExists; +// import static com.commercetools.project.sync.util.IntegrationTestUtils.cleanUpProjects; +// import static com.commercetools.project.sync.util.IntegrationTestUtils.createITSyncerFactory; +// import static com.commercetools.project.sync.util.QueryUtils.queryAndExecute; +// import static com.commercetools.project.sync.util.SyncUtils.APPLICATION_DEFAULT_NAME; +// import static com.commercetools.project.sync.util.SyncUtils.DEFAULT_RUNNER_NAME; +// import static +// com.commercetools.project.sync.util.TestUtils.assertCartDiscountSyncerLoggingEvents; +// import static com.commercetools.project.sync.util.TestUtils.assertCategorySyncerLoggingEvents; +// import static +// com.commercetools.project.sync.util.TestUtils.assertCustomObjectSyncerLoggingEvents; +// import static com.commercetools.project.sync.util.TestUtils.assertCustomerSyncerLoggingEvents; +// import static +// com.commercetools.project.sync.util.TestUtils.assertInventoryEntrySyncerLoggingEvents; +// import static com.commercetools.project.sync.util.TestUtils.assertProductSyncerLoggingEvents; +// import static com.commercetools.project.sync.util.TestUtils.assertProductTypeSyncerLoggingEvents; +// import static +// com.commercetools.project.sync.util.TestUtils.assertShoppingListSyncerLoggingEvents; +// import static com.commercetools.project.sync.util.TestUtils.assertStateSyncerLoggingEvents; +// import static com.commercetools.project.sync.util.TestUtils.assertTaxCategorySyncerLoggingEvents; +// import static com.commercetools.project.sync.util.TestUtils.assertTypeSyncerLoggingEvents; +// import static io.sphere.sdk.models.LocalizedString.ofEnglish; +// import static java.lang.String.format; +// import static java.util.Collections.emptyList; +// import static java.util.Collections.singletonList; +// import static org.assertj.core.api.Assertions.assertThat; +// +// import com.commercetools.project.sync.cartdiscount.CartDiscountSyncer; +// import com.commercetools.project.sync.category.CategorySyncer; +// import com.commercetools.project.sync.customer.CustomerSyncer; +// import com.commercetools.project.sync.customobject.CustomObjectSyncer; +// import com.commercetools.project.sync.inventoryentry.InventoryEntrySyncer; +// import com.commercetools.project.sync.model.response.LastSyncCustomObject; +// import com.commercetools.project.sync.product.ProductSyncer; +// import com.commercetools.project.sync.producttype.ProductTypeSyncer; +// import com.commercetools.project.sync.shoppinglist.ShoppingListSyncer; +// import com.commercetools.project.sync.state.StateSyncer; +// import com.commercetools.project.sync.taxcategory.TaxCategorySyncer; +// import com.commercetools.project.sync.type.TypeSyncer; +// import com.commercetools.sync.commons.helpers.BaseSyncStatistics; +// import com.commercetools.sync.products.helpers.ProductSyncStatistics; +// import com.fasterxml.jackson.databind.JsonNode; +// import com.fasterxml.jackson.databind.node.JsonNodeFactory; +// import com.fasterxml.jackson.databind.node.ObjectNode; +// import com.neovisionaries.i18n.CountryCode; +// import io.sphere.sdk.cartdiscounts.CartDiscount; +// import io.sphere.sdk.cartdiscounts.CartDiscountDraft; +// import io.sphere.sdk.cartdiscounts.CartDiscountDraftBuilder; +// import io.sphere.sdk.cartdiscounts.CartDiscountValue; +// import io.sphere.sdk.cartdiscounts.ShippingCostTarget; +// import io.sphere.sdk.cartdiscounts.commands.CartDiscountCreateCommand; +// import io.sphere.sdk.cartdiscounts.queries.CartDiscountQuery; +// import io.sphere.sdk.categories.Category; +// import io.sphere.sdk.categories.CategoryDraft; +// import io.sphere.sdk.categories.CategoryDraftBuilder; +// import io.sphere.sdk.categories.commands.CategoryCreateCommand; +// import io.sphere.sdk.categories.queries.CategoryQuery; +// import io.sphere.sdk.client.SphereClient; +// import io.sphere.sdk.customers.Customer; +// import io.sphere.sdk.customers.CustomerDraft; +// import io.sphere.sdk.customers.CustomerDraftBuilder; +// import io.sphere.sdk.customers.CustomerName; +// import io.sphere.sdk.customers.CustomerSignInResult; +// import io.sphere.sdk.customers.commands.CustomerCreateCommand; +// import io.sphere.sdk.customers.commands.CustomerUpdateCommand; +// import io.sphere.sdk.customers.commands.updateactions.ChangeName; +// import io.sphere.sdk.customers.queries.CustomerQuery; +// import io.sphere.sdk.customobjects.CustomObject; +// import io.sphere.sdk.customobjects.CustomObjectDraft; +// import io.sphere.sdk.customobjects.commands.CustomObjectUpsertCommand; +// import io.sphere.sdk.customobjects.queries.CustomObjectQuery; +// import io.sphere.sdk.inventory.InventoryEntry; +// import io.sphere.sdk.inventory.InventoryEntryDraft; +// import io.sphere.sdk.inventory.InventoryEntryDraftBuilder; +// import io.sphere.sdk.inventory.commands.InventoryEntryCreateCommand; +// import io.sphere.sdk.inventory.queries.InventoryEntryQuery; +// import io.sphere.sdk.models.ResourceIdentifier; +// import io.sphere.sdk.products.Product; +// import io.sphere.sdk.products.ProductDraft; +// import io.sphere.sdk.products.ProductDraftBuilder; +// import io.sphere.sdk.products.ProductVariantDraftBuilder; +// import io.sphere.sdk.products.commands.ProductCreateCommand; +// import io.sphere.sdk.products.queries.ProductQuery; +// import io.sphere.sdk.producttypes.ProductType; +// import io.sphere.sdk.producttypes.ProductTypeDraft; +// import io.sphere.sdk.producttypes.ProductTypeDraftBuilder; +// import io.sphere.sdk.producttypes.commands.ProductTypeCreateCommand; +// import io.sphere.sdk.producttypes.queries.ProductTypeQuery; +// import io.sphere.sdk.queries.PagedQueryResult; +// import io.sphere.sdk.queries.QueryPredicate; +// import io.sphere.sdk.shoppinglists.LineItemDraft; +// import io.sphere.sdk.shoppinglists.LineItemDraftBuilder; +// import io.sphere.sdk.shoppinglists.ShoppingList; +// import io.sphere.sdk.shoppinglists.ShoppingListDraft; +// import io.sphere.sdk.shoppinglists.ShoppingListDraftBuilder; +// import io.sphere.sdk.shoppinglists.commands.ShoppingListCreateCommand; +// import io.sphere.sdk.shoppinglists.commands.ShoppingListDeleteCommand; +// import io.sphere.sdk.shoppinglists.queries.ShoppingListQuery; +// import io.sphere.sdk.states.State; +// import io.sphere.sdk.states.StateDraft; +// import io.sphere.sdk.states.StateDraftBuilder; +// import io.sphere.sdk.states.StateType; +// import io.sphere.sdk.states.commands.StateCreateCommand; +// import io.sphere.sdk.states.queries.StateQuery; +// import io.sphere.sdk.taxcategories.TaxCategory; +// import io.sphere.sdk.taxcategories.TaxCategoryDraft; +// import io.sphere.sdk.taxcategories.TaxCategoryDraftBuilder; +// import io.sphere.sdk.taxcategories.TaxRateDraft; +// import io.sphere.sdk.taxcategories.TaxRateDraftBuilder; +// import io.sphere.sdk.taxcategories.commands.TaxCategoryCreateCommand; +// import io.sphere.sdk.taxcategories.queries.TaxCategoryQuery; +// import io.sphere.sdk.types.CustomFieldsDraft; +// import io.sphere.sdk.types.CustomFieldsDraftBuilder; +// import io.sphere.sdk.types.ResourceTypeIdsSetBuilder; +// import io.sphere.sdk.types.Type; +// import io.sphere.sdk.types.TypeDraft; +// import io.sphere.sdk.types.TypeDraftBuilder; +// import io.sphere.sdk.types.commands.TypeCreateCommand; +// import io.sphere.sdk.types.queries.TypeQuery; +// import java.time.ZonedDateTime; +// import java.util.Collections; +// import java.util.concurrent.CompletableFuture; +// import java.util.concurrent.ExecutionException; +// import javax.annotation.Nonnull; +// import org.junit.jupiter.api.AfterAll; +// import org.junit.jupiter.api.BeforeEach; +// import org.junit.jupiter.api.Test; +// import uk.org.lidalia.slf4jext.Level; +// import uk.org.lidalia.slf4jtest.TestLogger; +// import uk.org.lidalia.slf4jtest.TestLoggerFactory; +// +//// This will suppress MoreThanOneLogger warnings in this class +// @SuppressWarnings("PMD.MoreThanOneLogger") +// class CliRunnerIT { +// +// private static final TestLogger productSyncerTestLogger = +// TestLoggerFactory.getTestLogger(ProductSyncer.class); +// private static final TestLogger cliRunnerTestLogger = +// TestLoggerFactory.getTestLogger(CliRunner.class); +// private static final TestLogger productTypeSyncerTestLogger = +// TestLoggerFactory.getTestLogger(ProductTypeSyncer.class); +// private static final TestLogger customerSyncerTestLogger = +// TestLoggerFactory.getTestLogger(CustomerSyncer.class); +// private static final TestLogger shoppingListSyncerTestLogger = +// TestLoggerFactory.getTestLogger(ShoppingListSyncer.class); +// private static final TestLogger stateSyncerTestLogger = +// TestLoggerFactory.getTestLogger(StateSyncer.class); +// private static final TestLogger inventoryEntrySyncerTestLogger = +// TestLoggerFactory.getTestLogger(InventoryEntrySyncer.class); +// private static final TestLogger customObjectSyncerTestLogger = +// TestLoggerFactory.getTestLogger(CustomObjectSyncer.class); +// private static final TestLogger typeSyncerTestLogger = +// TestLoggerFactory.getTestLogger(TypeSyncer.class); +// private static final TestLogger categorySyncerTestLogger = +// TestLoggerFactory.getTestLogger(CategorySyncer.class); +// private static final TestLogger cartDiscountSyncerTestLogger = +// TestLoggerFactory.getTestLogger(CartDiscountSyncer.class); +// private static final TestLogger taxCategorySyncerTestLogger = +// TestLoggerFactory.getTestLogger(TaxCategorySyncer.class); +// +// private static final String RESOURCE_KEY = "foo"; +// private static final String PROJECT_SYNC_CONTAINER_NAME = +// "commercetools-project-sync.runnerName.ProductSync.timestampGenerator"; +// +// @BeforeEach +// void setup() throws ExecutionException, InterruptedException { +// cliRunnerTestLogger.clearAll(); +// productSyncerTestLogger.clearAll(); +// productTypeSyncerTestLogger.clearAll(); +// customerSyncerTestLogger.clearAll(); +// shoppingListSyncerTestLogger.clearAll(); +// stateSyncerTestLogger.clearAll(); +// inventoryEntrySyncerTestLogger.clearAll(); +// customObjectSyncerTestLogger.clearAll(); +// typeSyncerTestLogger.clearAll(); +// categorySyncerTestLogger.clearAll(); +// cartDiscountSyncerTestLogger.clearAll(); +// taxCategorySyncerTestLogger.clearAll(); +// cleanUpProjects(CTP_SOURCE_CLIENT, CTP_TARGET_CLIENT); +// setupSourceProjectData(CTP_SOURCE_CLIENT); +// } +// +// static void setupSourceProjectData(@Nonnull final SphereClient sourceProjectClient) +// throws ExecutionException, InterruptedException { +// final ProductTypeDraft productTypeDraft = +// ProductTypeDraftBuilder.of( +// RESOURCE_KEY, "sample-product-type", "a productType for t-shirts", emptyList()) +// .build(); +// +// final ProductType productType = +// sourceProjectClient +// .execute(ProductTypeCreateCommand.of(productTypeDraft)) +// .toCompletableFuture() +// .join(); +// +// final TypeDraft typeDraft = +// TypeDraftBuilder.of( +// RESOURCE_KEY, +// ofEnglish("category-custom-type"), +// ResourceTypeIdsSetBuilder.of().addCategories().add("shopping-list")) +// .build(); +// +// final StateDraft stateDraft = +// StateDraftBuilder.of(RESOURCE_KEY, StateType.PRODUCT_STATE) +// .roles(Collections.emptySet()) +// .description(ofEnglish("State 1")) +// .name(ofEnglish("State 1")) +// .initial(true) +// .transitions(Collections.emptySet()) +// .build(); +// final State state = +// +// sourceProjectClient.execute(StateCreateCommand.of(stateDraft)).toCompletableFuture().join(); +// +// final CompletableFuture typeFuture = +// sourceProjectClient.execute(TypeCreateCommand.of(typeDraft)).toCompletableFuture(); +// +// final TaxRateDraft taxRateDraft = +// TaxRateDraftBuilder.of("Tax-Rate-Name-1", 0.3, false, CountryCode.DE).build(); +// +// final TaxCategoryDraft taxCategoryDraft = +// TaxCategoryDraftBuilder.of( +// "Tax-Category-Name-1", singletonList(taxRateDraft), "Tax-Category-Description-1") +// .key(RESOURCE_KEY) +// .build(); +// +// final TaxCategory taxCategory = +// sourceProjectClient +// .execute(TaxCategoryCreateCommand.of(taxCategoryDraft)) +// .toCompletableFuture() +// .join(); +// +// final ObjectNode customObjectValue = JsonNodeFactory.instance.objectNode().put("name", +// "value"); +// final CustomObjectDraft customObjectDraft = +// CustomObjectDraft.ofUnversionedUpsert(RESOURCE_KEY, RESOURCE_KEY, customObjectValue); +// // following custom object should not be synced as it's created by the project-sync itself +// final CustomObjectDraft customObjectToIgnore = +// CustomObjectDraft.ofUnversionedUpsert( +// PROJECT_SYNC_CONTAINER_NAME, "timestampGenerator", customObjectValue); +// +// final CompletableFuture> customObjectFuture1 = +// sourceProjectClient +// .execute(CustomObjectUpsertCommand.of(customObjectDraft)) +// .toCompletableFuture(); +// +// final CompletableFuture> customObjectFuture2 = +// sourceProjectClient +// .execute(CustomObjectUpsertCommand.of(customObjectToIgnore)) +// .toCompletableFuture(); +// +// final CategoryDraft categoryDraft = +// CategoryDraftBuilder.of(ofEnglish("t-shirts"), ofEnglish("t-shirts")) +// .key(RESOURCE_KEY) +// .build(); +// +// final CompletableFuture categoryFuture = +// +// sourceProjectClient.execute(CategoryCreateCommand.of(categoryDraft)).toCompletableFuture(); +// +// final CustomerDraft customerDraft = +// CustomerDraftBuilder.of("test@email.com", "testPassword").key(RESOURCE_KEY).build(); +// +// final CompletableFuture customerFuture = +// +// sourceProjectClient.execute(CustomerCreateCommand.of(customerDraft)).toCompletableFuture(); +// +// CompletableFuture.allOf( +// typeFuture, customObjectFuture1, customObjectFuture2, categoryFuture, customerFuture) +// .join(); +// +// final ProductDraft productDraft = +// ProductDraftBuilder.of( +// productType, +// ofEnglish("V-neck Tee"), +// ofEnglish("v-neck-tee"), +// ProductVariantDraftBuilder.of().key(RESOURCE_KEY).sku(RESOURCE_KEY).build()) +// .state(state) +// .taxCategory(taxCategory) +// .key(RESOURCE_KEY) +// .publish(true) +// .build(); +// +// final CompletableFuture productFuture = +// sourceProjectClient.execute(ProductCreateCommand.of(productDraft)).toCompletableFuture(); +// +// final InventoryEntryDraft inventoryEntryDraft = +// InventoryEntryDraftBuilder.of(RESOURCE_KEY, 1L).build(); +// +// final CompletableFuture inventoryFuture = +// sourceProjectClient +// .execute(InventoryEntryCreateCommand.of(inventoryEntryDraft)) +// .toCompletableFuture(); +// +// final CartDiscountDraft cartDiscountDraft = +// CartDiscountDraftBuilder.of( +// ofEnglish("my-cart-discount"), +// "1 = 1", +// CartDiscountValue.ofRelative(1), +// ShippingCostTarget.of(), +// "0.1", +// true) +// .key(RESOURCE_KEY) +// .build(); +// +// final CompletableFuture cartDiscountFuture = +// sourceProjectClient +// .execute(CartDiscountCreateCommand.of(cartDiscountDraft)) +// .toCompletableFuture(); +// CompletableFuture.allOf(productFuture, inventoryFuture, cartDiscountFuture); +// +// final CustomerSignInResult customerSignInResult = customerFuture.get(); +// final Product product = productFuture.get(); +// final LineItemDraft lineItemDraft = LineItemDraftBuilder.of(product.getId()).build(); +// final CustomFieldsDraft customFieldsDraft = +// CustomFieldsDraftBuilder.ofTypeId(typeFuture.get().getId()).build(); +// +// final ShoppingListDraft shoppingListDraft = +// ShoppingListDraftBuilder.of(ofEnglish("shoppingList-name")) +// .key(RESOURCE_KEY) +// .customer(ResourceIdentifier.ofId(customerSignInResult.getCustomer().getId())) +// .lineItems(Collections.singletonList(lineItemDraft)) +// .custom(customFieldsDraft) +// .build(); +// +// sourceProjectClient +// .execute(ShoppingListCreateCommand.of(shoppingListDraft)) +// .toCompletableFuture() +// .join(); +// } +// +// @AfterAll +// static void tearDownSuite() { +// cleanUpProjects(CTP_SOURCE_CLIENT, CTP_TARGET_CLIENT); +// } +// +// @Test +// void run_WithSyncAsArgumentWithAllArg_ShouldExecuteAllSyncers() { +// // test +// CliRunner.of().run(new String[] {"-s", "all"}, createITSyncerFactory()); +// +// // assertions +// assertAllSyncersLoggingEvents(1); +// +// assertAllResourcesAreSyncedToTarget(CTP_TARGET_CLIENT); +// } +// +// @Test +// void run_WithSyncAsArgumentWhenAllArgumentsPassed_ShouldExecuteAllSyncers() { +// // test +// CliRunner.of() +// .run( +// new String[] { +// "-s", +// "types", +// "productTypes", +// "customers", +// "customObjects", +// "taxCategories", +// "categories", +// "inventoryEntries", +// "cartDiscounts", +// "states", +// "products", +// "shoppingLists" +// }, +// createITSyncerFactory()); +// +// // assertions +// assertAllSyncersLoggingEvents(1); +// +// assertAllResourcesAreSyncedToTarget(CTP_TARGET_CLIENT); +// } +// +// @Test +// void run_WithSyncAsArgumentWithCustomersAndShoppingLists_ShouldExecuteGivenSyncers() { +// prepareDataForShoppingListSync(CTP_SOURCE_CLIENT); +// +// // test +// CliRunner.of().run(new String[] {"-s", "customers", "shoppingLists"}, +// createITSyncerFactory()); +// +// // assertions +// assertCustomerSyncerLoggingEvents(customerSyncerTestLogger, 1); +// assertShoppingListSyncerLoggingEvents(shoppingListSyncerTestLogger, 1); +// +// assertCustomersAreSyncedCorrectly(CTP_TARGET_CLIENT); +// assertShoppingListsAreSyncedCorrectly(CTP_TARGET_CLIENT); +// +// final String sourceProjectKey = CTP_SOURCE_CLIENT.getConfig().getProjectKey(); +// +// assertLastSyncCustomObjectExists( +// CTP_TARGET_CLIENT, sourceProjectKey, "customerSync", "runnerName"); +// assertLastSyncCustomObjectExists( +// CTP_TARGET_CLIENT, sourceProjectKey, "shoppingListSync", "runnerName"); +// } +// +// @Test +// void +// +// run_WithSyncAsArgumentWithCategoriesTaxCategoriesAndCartDiscounts_ShouldExecuteGivenSyncers() { +// // test +// CliRunner.of() +// .run( +// new String[] {"-s", "taxCategories", "categories", "cartDiscounts"}, +// createITSyncerFactory()); +// // assertions +// assertCategorySyncerLoggingEvents(categorySyncerTestLogger, 1); +// assertTaxCategorySyncerLoggingEvents(taxCategorySyncerTestLogger, 1); +// assertCartDiscountSyncerLoggingEvents(cartDiscountSyncerTestLogger, 1); +// +// assertCategoriesAreSyncedCorrectly(CTP_TARGET_CLIENT); +// assertTaxCategoriesAreSyncedCorrectly(CTP_TARGET_CLIENT); +// assertCartDiscountsAreSyncedCorrectly(CTP_TARGET_CLIENT); +// +// final String sourceProjectKey = CTP_SOURCE_CLIENT.getConfig().getProjectKey(); +// +// assertLastSyncCustomObjectExists( +// CTP_TARGET_CLIENT, sourceProjectKey, "categorySync", "runnerName"); +// assertLastSyncCustomObjectExists( +// CTP_TARGET_CLIENT, sourceProjectKey, "taxCategorySync", "runnerName"); +// assertLastSyncCustomObjectExists( +// CTP_TARGET_CLIENT, sourceProjectKey, "cartDiscountSync", "runnerName"); +// } +// +// @Test +// void +// run_WithSyncAsArgumentWithProductTypesCategoriesAndShoppingLists_ShouldExecuteGivenSyncers() +// { +// // preparation +// prepareDataForShoppingListSync(CTP_SOURCE_CLIENT); +// +// // test +// CliRunner.of() +// .run( +// new String[] {"-s", "productTypes", "categories", "shoppingLists"}, +// createITSyncerFactory()); +// // assertions +// assertProductTypeSyncerLoggingEvents(productTypeSyncerTestLogger, 1); +// assertCategorySyncerLoggingEvents(categorySyncerTestLogger, 1); +// assertShoppingListSyncerLoggingEvents(shoppingListSyncerTestLogger, 1); +// +// assertProductTypesAreSyncedCorrectly(CTP_TARGET_CLIENT); +// assertCategoriesAreSyncedCorrectly(CTP_TARGET_CLIENT); +// assertShoppingListsAreSyncedCorrectly(CTP_TARGET_CLIENT); +// +// final String sourceProjectKey = CTP_SOURCE_CLIENT.getConfig().getProjectKey(); +// +// assertLastSyncCustomObjectExists( +// CTP_TARGET_CLIENT, sourceProjectKey, "categorySync", "runnerName"); +// assertLastSyncCustomObjectExists( +// CTP_TARGET_CLIENT, sourceProjectKey, "productTypeSync", "runnerName"); +// assertLastSyncCustomObjectExists( +// CTP_TARGET_CLIENT, sourceProjectKey, "shoppingListSync", "runnerName"); +// } +// +// @Test +// void +// +// run_WithSyncAsArgumentWithProductsAndShoppingListsAlongWithTheirReferencedResources_ShouldExecuteGivenSyncers() { +// // test +// CliRunner.of() +// .run( +// new String[] { +// "-s", +// "types", +// "productTypes", +// "states", +// "taxCategories", +// "products", +// "customers", +// "shoppingLists" +// }, +// createITSyncerFactory()); +// // assertions +// assertProductSyncerLoggingEvents(productSyncerTestLogger, 1); +// +// assertTypesAreSyncedCorrectly(CTP_TARGET_CLIENT); +// assertProductsAreSyncedCorrectly(CTP_TARGET_CLIENT); +// assertProductTypesAreSyncedCorrectly(CTP_TARGET_CLIENT); +// assertStatesAreSyncedCorrectly(CTP_TARGET_CLIENT); +// assertTaxCategoriesAreSyncedCorrectly(CTP_TARGET_CLIENT); +// assertCustomersAreSyncedCorrectly(CTP_TARGET_CLIENT); +// assertShoppingListsAreSyncedCorrectly(CTP_TARGET_CLIENT); +// +// final String sourceProjectKey = CTP_SOURCE_CLIENT.getConfig().getProjectKey(); +// +// assertLastSyncCustomObjectExists(CTP_TARGET_CLIENT, sourceProjectKey, "typeSync", +// "runnerName"); +// assertLastSyncCustomObjectExists( +// CTP_TARGET_CLIENT, sourceProjectKey, "productSync", "runnerName"); +// assertLastSyncCustomObjectExists( +// CTP_TARGET_CLIENT, sourceProjectKey, "productTypeSync", "runnerName"); +// assertLastSyncCustomObjectExists( +// CTP_TARGET_CLIENT, sourceProjectKey, "stateSync", "runnerName"); +// assertLastSyncCustomObjectExists( +// CTP_TARGET_CLIENT, sourceProjectKey, "taxCategorySync", "runnerName"); +// assertLastSyncCustomObjectExists( +// CTP_TARGET_CLIENT, sourceProjectKey, "customerSync", "runnerName"); +// assertLastSyncCustomObjectExists( +// CTP_TARGET_CLIENT, sourceProjectKey, "shoppingListSync", "runnerName"); +// } +// +// @Test +// void +// run_WithCustomerSyncAsArgument_ShouldSyncCustomersAndStoreLastSyncTimestampsAsCustomObject() +// { +// // test +// CliRunner.of().run(new String[] {"-s", "customers"}, createITSyncerFactory()); +// // assertions +// assertThat(customerSyncerTestLogger.getAllLoggingEvents()).hasSize(2); +// +// assertCustomerSyncerLoggingEvents(customerSyncerTestLogger, 1); +// +// assertCustomersAreSyncedCorrectly(CTP_TARGET_CLIENT); +// +// final String sourceProjectKey = CTP_SOURCE_CLIENT.getConfig().getProjectKey(); +// +// assertLastSyncCustomObjectExists( +// CTP_TARGET_CLIENT, sourceProjectKey, "customerSync", "runnerName"); +// } +// +// @Test +// void run_WithUpdatedCustomer_ShouldSyncCustomersAndStoreLastSyncTimestampsAsCustomObject() { +// ZonedDateTime lastModifiedTime = null; +// // preparation +// final SyncerFactory syncerFactory = createITSyncerFactory(); +// +// // test +// CliRunner.of().run(new String[] {"-s", "customers"}, syncerFactory); +// +// lastModifiedTime = +// getCustomObjectLastModifiedTime(CTP_TARGET_CLIENT, "customerSync", "runnerName"); +// updateCustomerSourceObject(CTP_SOURCE_CLIENT); +// +// // test +// CliRunner.of().run(new String[] {"-s", "customers"}, syncerFactory); +// +// assertUpdatedCustomersAreSyncedCorrectly(CTP_SOURCE_CLIENT, CTP_TARGET_CLIENT); +// +// assertUpdatedCustomObjectTimestampAfterSync( +// CTP_TARGET_CLIENT, "customerSync", "runnerName", lastModifiedTime); +// } +// +// private void assertUpdatedCustomObjectTimestampAfterSync( +// @Nonnull final SphereClient targetClient, +// @Nonnull final String syncModuleName, +// @Nonnull final String runnerName, +// @Nonnull final ZonedDateTime lastModifiedTime) { +// final PagedQueryResult> lastSyncResult = +// fetchLastSyncCustomObject(targetClient, syncModuleName, runnerName); +// +// assertThat(lastModifiedTime) +// .isBefore(lastSyncResult.getResults().get(0).getValue().getLastSyncTimestamp()); +// } +// +// private ZonedDateTime getCustomObjectLastModifiedTime( +// @Nonnull final SphereClient targetClient, +// @Nonnull final String syncModuleName, +// @Nonnull final String runnerName) { +// final PagedQueryResult> lastSyncResult = +// fetchLastSyncCustomObject(targetClient, syncModuleName, runnerName); +// +// return lastSyncResult.getResults().get(0).getValue().getLastSyncTimestamp(); +// } +// +// private void updateCustomerSourceObject(@Nonnull final SphereClient sourceProjectClient) { +// final PagedQueryResult customerPagedQueryResult = +// sourceProjectClient +// .execute( +// CustomerQuery.of() +// .withPredicates(QueryPredicate.of(format("key=\"%s\"", RESOURCE_KEY)))) +// .toCompletableFuture() +// .join(); +// final Customer customer = customerPagedQueryResult.getResults().get(0); +// +// sourceProjectClient +// .execute( +// CustomerUpdateCommand.of( +// customer, +// ChangeName.of(CustomerName.ofFirstAndLastName("testFirstName", "testLastName")))) +// .toCompletableFuture() +// .join(); +// } +// +// private void assertUpdatedCustomersAreSyncedCorrectly( +// @Nonnull final SphereClient cspClient, @Nonnull final SphereClient ctpClient) { +// final PagedQueryResult sourceCustomerPagedQueryResult = +// cspClient +// .execute( +// CustomerQuery.of() +// .withPredicates(QueryPredicate.of(format("key=\"%s\"", RESOURCE_KEY)))) +// .toCompletableFuture() +// .join(); +// Customer sourceCustomer = sourceCustomerPagedQueryResult.getResults().get(0); +// +// final PagedQueryResult targetCustomerPagedQueryResult = +// ctpClient +// .execute( +// CustomerQuery.of() +// .withPredicates(QueryPredicate.of(format("key=\"%s\"", RESOURCE_KEY)))) +// .toCompletableFuture() +// .join(); +// Customer targetCustomer = targetCustomerPagedQueryResult.getResults().get(0); +// +// assertThat(sourceCustomer.getName()).isEqualTo(targetCustomer.getName()); +// } +// +// @Test +// void +// +// run_WithShoppingListSyncAsArgument_ShouldSyncShoppingListsAndStoreLastSyncTimestampsAsCustomObject() { +// // preparation +// // Shopping List contains Product, Customer and Type references. So, here it is recreating +// // ShoppingList without any references. +// prepareDataForShoppingListSync(CTP_SOURCE_CLIENT); +// +// // test +// CliRunner.of().run(new String[] {"-s", "shoppingLists"}, createITSyncerFactory()); +// +// // create clients again (for assertions and cleanup), since the run method closes the clients +// // after execution is done. +// // assertions +// assertThat(shoppingListSyncerTestLogger.getAllLoggingEvents()).hasSize(2); +// +// assertShoppingListSyncerLoggingEvents(shoppingListSyncerTestLogger, 1); +// +// assertShoppingListsAreSyncedCorrectly(CTP_TARGET_CLIENT); +// +// final String sourceProjectKey = CTP_SOURCE_CLIENT.getConfig().getProjectKey(); +// +// assertLastSyncCustomObjectExists( +// CTP_TARGET_CLIENT, sourceProjectKey, "shoppingListSync", "runnerName"); +// } +// +// private void prepareDataForShoppingListSync(SphereClient sourceClient) { +// queryAndExecute(sourceClient, ShoppingListQuery.of(), ShoppingListDeleteCommand::of).join(); +// final ShoppingListDraft shoppingListDraft = +// ShoppingListDraftBuilder.of(ofEnglish("shoppingList-name")).key(RESOURCE_KEY).build(); +// +// sourceClient +// .execute(ShoppingListCreateCommand.of(shoppingListDraft)) +// .toCompletableFuture() +// .join(); +// } +// +// @Test +// void +// +// run_WithCustomObjectSyncAsArgument_ShouldSyncCustomObjectsWithoutProjectSyncGeneratedCustomObjects() { +// // test +// CliRunner.of().run(new String[] {"-s", "customObjects"}, createITSyncerFactory()); +// // assertions +// // assertions +// assertThat(customObjectSyncerTestLogger.getAllLoggingEvents()).hasSize(2); +// +// assertCustomObjectSyncerLoggingEvents(customObjectSyncerTestLogger, 1); +// } +// +// @Test +// void +// +// run_WithProductTypeSyncAsArgument_ShouldExecuteProductTypeSyncerAndStoreLastSyncTimestampsAsCustomObject() { +// // test +// CliRunner.of().run(new String[] {"-s", "productTypes"}, createITSyncerFactory()); +// // assertions +// assertThat(productTypeSyncerTestLogger.getAllLoggingEvents()).hasSize(2); +// +// assertProductTypeSyncerLoggingEvents(productTypeSyncerTestLogger, 1); +// +// assertProductTypesAreSyncedCorrectly(CTP_TARGET_CLIENT); +// +// final ZonedDateTime lastSyncTimestamp = +// assertCurrentCtpTimestampGeneratorAndGetLastModifiedAt( +// CTP_TARGET_CLIENT, DEFAULT_RUNNER_NAME, "ProductTypeSync"); +// +// final String sourceProjectKey = CTP_SOURCE_CLIENT.getConfig().getProjectKey(); +// +// assertLastSyncCustomObjectIsCorrect( +// CTP_TARGET_CLIENT, +// sourceProjectKey, +// "productTypeSync", +// DEFAULT_RUNNER_NAME, +// ProductSyncStatistics.class, +// lastSyncTimestamp); +// } +// +// private static void assertTypesAreSyncedCorrectly(@Nonnull final SphereClient ctpClient) { +// final String queryPredicate = format("key=\"%s\"", RESOURCE_KEY); +// +// final PagedQueryResult typeQueryResult = +// ctpClient +// .execute(TypeQuery.of().withPredicates(QueryPredicate.of(queryPredicate))) +// .toCompletableFuture() +// .join(); +// +// assertThat(typeQueryResult.getResults()) +// .hasSize(1) +// .singleElement() +// .satisfies(productType -> assertThat(productType.getKey()).isEqualTo(RESOURCE_KEY)); +// } +// +// private static void assertProductTypesAreSyncedCorrectly(@Nonnull final SphereClient ctpClient) +// { +// +// final PagedQueryResult productTypeQueryResult = +// ctpClient.execute(ProductTypeQuery.of().byKey(RESOURCE_KEY)).toCompletableFuture().join(); +// +// assertThat(productTypeQueryResult.getResults()) +// .hasSize(1) +// .singleElement() +// .satisfies(productType -> assertThat(productType.getKey()).isEqualTo(RESOURCE_KEY)); +// } +// +// private static void assertProductsAreSyncedCorrectly(@Nonnull final SphereClient ctpClient) { +// +// final PagedQueryResult productQueryResult = +// ctpClient.execute(ProductQuery.of()).toCompletableFuture().join(); +// +// assertThat(productQueryResult.getResults()) +// .hasSize(1) +// .singleElement() +// .satisfies(product -> assertThat(product.getKey()).isEqualTo(RESOURCE_KEY)); +// } +// +// private static void assertCustomersAreSyncedCorrectly(@Nonnull final SphereClient ctpClient) { +// final PagedQueryResult customerPagedQueryResult = +// ctpClient +// .execute( +// CustomerQuery.of() +// .withPredicates(QueryPredicate.of(format("key=\"%s\"", RESOURCE_KEY)))) +// .toCompletableFuture() +// .join(); +// assertThat(customerPagedQueryResult.getResults()).hasSize(1); +// } +// +// private static void assertShoppingListsAreSyncedCorrectly(@Nonnull final SphereClient ctpClient) +// { +// final PagedQueryResult shoppingListPagedQueryResult = +// ctpClient +// .execute( +// ShoppingListQuery.of() +// .withPredicates(QueryPredicate.of(format("key=\"%s\"", RESOURCE_KEY)))) +// .toCompletableFuture() +// .join(); +// assertThat(shoppingListPagedQueryResult.getResults()).hasSize(1); +// } +// +// private static void assertCategoriesAreSyncedCorrectly(@Nonnull final SphereClient ctpClient) { +// final PagedQueryResult categoryPagedQueryResult = +// ctpClient +// .execute( +// CategoryQuery.of() +// .withPredicates(QueryPredicate.of(format("key=\"%s\"", RESOURCE_KEY)))) +// .toCompletableFuture() +// .join(); +// assertThat(categoryPagedQueryResult.getResults()).hasSize(1); +// } +// +// private static void assertStatesAreSyncedCorrectly(@Nonnull final SphereClient ctpClient) { +// final PagedQueryResult statePagedQueryResult = +// ctpClient +// .execute( +// StateQuery.of() +// .withPredicates(QueryPredicate.of(format("key=\"%s\"", RESOURCE_KEY)))) +// .toCompletableFuture() +// .join(); +// assertThat(statePagedQueryResult.getResults()).hasSize(1); +// } +// +// private static void assertTaxCategoriesAreSyncedCorrectly(@Nonnull final SphereClient ctpClient) +// { +// final PagedQueryResult taxCategoryPagedQueryResult = +// ctpClient +// .execute( +// TaxCategoryQuery.of() +// .withPredicates(QueryPredicate.of(format("key=\"%s\"", RESOURCE_KEY)))) +// .toCompletableFuture() +// .join(); +// assertThat(taxCategoryPagedQueryResult.getResults()).hasSize(1); +// } +// +// private static void assertCartDiscountsAreSyncedCorrectly(@Nonnull final SphereClient ctpClient) +// { +// final PagedQueryResult cartDiscountPagedQueryResult = +// ctpClient +// .execute( +// CartDiscountQuery.of() +// .withPredicates(QueryPredicate.of(format("key=\"%s\"", RESOURCE_KEY)))) +// .toCompletableFuture() +// .join(); +// assertThat(cartDiscountPagedQueryResult.getResults()).hasSize(1); +// } +// +// private void assertLastSyncCustomObjectIsCorrect( +// @Nonnull final SphereClient targetClient, +// @Nonnull final String sourceProjectKey, +// @Nonnull final String syncModuleName, +// @Nonnull final String syncRunnerName, +// @Nonnull final Class statisticsClass, +// @Nonnull final ZonedDateTime lastSyncTimestamp) { +// +// final PagedQueryResult> lastSyncResult = +// fetchLastSyncCustomObject(targetClient, syncModuleName, syncRunnerName); +// +// assertThat(lastSyncResult.getResults()) +// .hasSize(1) +// .singleElement() +// .satisfies( +// lastSyncCustomObject -> { +// assertThat(lastSyncCustomObject.getKey()).isEqualTo(sourceProjectKey); +// assertThat(lastSyncCustomObject.getValue()) +// .satisfies( +// value -> { +// // Excluding til BaseStatisticsDeserializer works with correct type. +// // +// assertThat(value.getLastSyncStatistics()).isInstanceOf(statisticsClass); +// +// assertThat(value.getLastSyncStatistics().getProcessed().get()).isEqualTo(1); +// assertThat(value.getLastSyncTimestamp()) +// .isBeforeOrEqualTo(lastSyncTimestamp); +// }); +// }); +// } +// +// @Nonnull +// private ZonedDateTime assertCurrentCtpTimestampGeneratorAndGetLastModifiedAt( +// @Nonnull final SphereClient targetClient, +// @Nonnull final String runnerName, +// @Nonnull final String syncModuleName) { +// +// final CustomObjectQuery timestampGeneratorQuery = +// CustomObjectQuery.of(String.class) +// .byContainer( +// format( +// "%s.%s.%s.%s", +// APPLICATION_DEFAULT_NAME, runnerName, syncModuleName, +// TIMESTAMP_GENERATOR_KEY)); +// +// final PagedQueryResult> currentCtpTimestampGeneratorResults = +// targetClient.execute(timestampGeneratorQuery).toCompletableFuture().join(); +// +// assertThat(currentCtpTimestampGeneratorResults.getResults()) +// .hasSize(1) +// .singleElement() +// .satisfies( +// currentCtpTimestamp -> { +// assertThat(currentCtpTimestamp.getKey()).isEqualTo(TIMESTAMP_GENERATOR_KEY); +// assertThat(currentCtpTimestamp.getValue()) +// .matches( +// +// "[0-9a-fA-F]{8}\\-[0-9a-fA-F]{4}\\-[0-9a-fA-F]{4}\\-[0-9a-fA-F]{4}\\-[0-9a-fA-F]{12}"); +// }); +// +// return currentCtpTimestampGeneratorResults.getResults().get(0).getLastModifiedAt(); +// } +// +// @Test +// void +// +// run_WithSyncAsArgumentWithAllArgAsDeltaSync_ShouldExecuteAllSyncersAndStoreLastSyncTimestampsAsCustomObjects() { +// // test +// CliRunner.of().run(new String[] {"-s", "all", "-r", "runnerName"}, createITSyncerFactory()); +// assertAllSyncersLoggingEvents(1); +// +// assertAllResourcesAreSyncedToTarget(CTP_TARGET_CLIENT); +// assertCurrentCtpTimestampGeneratorAndGetLastModifiedAt( +// CTP_TARGET_CLIENT, "runnerName", "ProductTypeSync"); +// +// final String sourceProjectKey = CTP_SOURCE_CLIENT.getConfig().getProjectKey(); +// +// assertLastSyncCustomObjectExists( +// CTP_TARGET_CLIENT, sourceProjectKey, "productSync", "runnerName"); +// +// assertLastSyncCustomObjectExists( +// CTP_TARGET_CLIENT, sourceProjectKey, "categorySync", "runnerName"); +// +// assertLastSyncCustomObjectExists( +// CTP_TARGET_CLIENT, sourceProjectKey, "productTypeSync", "runnerName"); +// +// assertLastSyncCustomObjectExists(CTP_TARGET_CLIENT, sourceProjectKey, "typeSync", +// "runnerName"); +// +// assertLastSyncCustomObjectExists( +// CTP_TARGET_CLIENT, sourceProjectKey, "inventorySync", "runnerName"); +// +// assertLastSyncCustomObjectExists( +// CTP_TARGET_CLIENT, sourceProjectKey, "cartDiscountSync", "runnerName"); +// +// assertLastSyncCustomObjectExists( +// CTP_TARGET_CLIENT, sourceProjectKey, "stateSync", "runnerName"); +// +// assertLastSyncCustomObjectExists( +// CTP_TARGET_CLIENT, sourceProjectKey, "taxCategorySync", "runnerName"); +// +// assertLastSyncCustomObjectExists( +// CTP_TARGET_CLIENT, sourceProjectKey, "customObjectSync", "runnerName"); +// +// assertLastSyncCustomObjectExists( +// CTP_TARGET_CLIENT, sourceProjectKey, "customerSync", "runnerName"); +// } +// +// @Test +// void run_WithSyncAsArgumentWithAllArgAsFullSync_ShouldExecuteAllSyncers() { +// // test +// CliRunner.of() +// .run(new String[] {"-s", "all", "-r", "runnerName", "-f"}, createITSyncerFactory()); +// // assertions +// assertAllSyncersLoggingEvents(1); +// +// assertAllResourcesAreSyncedToTarget(CTP_TARGET_CLIENT); +// assertCurrentCtpTimestampGeneratorDoesntExist( +// CTP_TARGET_CLIENT, "runnerName", "ProductTypeSync"); +// assertNoProjectSyncCustomObjectExists(CTP_TARGET_CLIENT); +// } +// +// @Test +// void +// +// run_WithSyncAsArgumentWithAllArgAsFullSyncAndWithCustomQueryAndLimitForProducts_ShouldExecuteAllSyncers() { +// final Long limit = 100L; +// final String customQuery = "\"published=true AND masterVariant(key= \\\"foo\\\")\""; +// final String productQueryParametersValue = +// "{\"limit\": " + limit + ", \"where\": " + customQuery + "}"; +// +// // test +// CliRunner.of() +// .run( +// new String[] { +// "-s", +// "all", +// "-r", +// "runnerName", +// "-f", +// "-productQueryParameters", +// productQueryParametersValue +// }, +// createITSyncerFactory()); +// // assertions +// assertAllSyncersLoggingEvents(1); +// +// assertAllResourcesAreSyncedToTarget(CTP_TARGET_CLIENT); +// assertCurrentCtpTimestampGeneratorDoesntExist( +// CTP_TARGET_CLIENT, "runnerName", "ProductTypeSync"); +// assertNoProjectSyncCustomObjectExists(CTP_TARGET_CLIENT); +// } +// +// private void assertNoProjectSyncCustomObjectExists(@Nonnull final SphereClient targetClient) { +// final CustomObjectQuery lastSyncQuery = +// CustomObjectQuery.of(LastSyncCustomObject.class) +// .plusPredicates( +// customObjectQueryModel -> +// customObjectQueryModel.container().is(PROJECT_SYNC_CONTAINER_NAME)); +// final PagedQueryResult> lastSyncResult = +// targetClient.execute(lastSyncQuery).toCompletableFuture().join(); +// assertThat(lastSyncResult.getResults()).isEmpty(); +// } +// +// private void assertCurrentCtpTimestampGeneratorDoesntExist( +// @Nonnull final SphereClient targetClient, +// @Nonnull final String runnerName, +// @Nonnull final String syncModuleName) { +// +// final CustomObjectQuery timestampGeneratorQuery = +// CustomObjectQuery.of(String.class) +// .byContainer( +// format( +// "commercetools-project-sync.%s.%s.%s", +// runnerName, syncModuleName, TIMESTAMP_GENERATOR_KEY)); +// +// final PagedQueryResult> currentCtpTimestampGeneratorResults = +// targetClient.execute(timestampGeneratorQuery).toCompletableFuture().join(); +// +// assertThat(currentCtpTimestampGeneratorResults.getResults()).isEmpty(); +// } +// +// private void assertLastSyncCustomObjectExists( +// @Nonnull final SphereClient targetClient, +// @Nonnull final String sourceProjectKey, +// @Nonnull final String syncModuleName, +// @Nonnull final String runnerName) { +// +// final PagedQueryResult> lastSyncResult = +// fetchLastSyncCustomObject(targetClient, syncModuleName, runnerName); +// +// assertThat(lastSyncResult.getResults()) +// .hasSize(1) +// .singleElement() +// .satisfies( +// lastSyncCustomObject -> { +// assertThat(lastSyncCustomObject.getKey()).isEqualTo(sourceProjectKey); +// assertThat(lastSyncCustomObject.getValue()) +// .satisfies( +// value -> { +// assertThat(value.getLastSyncTimestamp()).isNotNull(); +// assertThat(value.getLastSyncDurationInMillis()).isNotNull(); +// assertThat(value.getApplicationVersion()).isNotNull(); +// }); +// }); +// } +// +// private PagedQueryResult> fetchLastSyncCustomObject( +// @Nonnull SphereClient targetClient, +// @Nonnull String syncModuleName, +// @Nonnull String runnerName) { +// final CustomObjectQuery lastSyncQuery = +// CustomObjectQuery.of(LastSyncCustomObject.class) +// .byContainer(format("%s.%s.%s", APPLICATION_DEFAULT_NAME, runnerName, +// syncModuleName)); +// +// return targetClient.execute(lastSyncQuery).toCompletableFuture().join(); +// } +// +// private static void assertAllResourcesAreSyncedToTarget( +// @Nonnull final SphereClient targetClient) { +// +// assertProductTypeExists(targetClient, RESOURCE_KEY); +// assertCategoryExists(targetClient, RESOURCE_KEY); +// assertProductExists(targetClient, RESOURCE_KEY, RESOURCE_KEY, RESOURCE_KEY); +// +// final String queryPredicate = format("key=\"%s\"", RESOURCE_KEY); +// +// final PagedQueryResult typeQueryResult = +// targetClient +// .execute(TypeQuery.of().withPredicates(QueryPredicate.of(queryPredicate))) +// .toCompletableFuture() +// .join(); +// +// assertThat(typeQueryResult.getResults()) +// .hasSize(1) +// .singleElement() +// .satisfies(type -> assertThat(type.getKey()).isEqualTo(RESOURCE_KEY)); +// +// final PagedQueryResult taxCategoryQueryResult = +// targetClient +// .execute(TaxCategoryQuery.of().withPredicates(QueryPredicate.of(queryPredicate))) +// .toCompletableFuture() +// .join(); +// +// assertThat(taxCategoryQueryResult.getResults()) +// .hasSize(1) +// .singleElement() +// .satisfies(taxCategory -> assertThat(taxCategory.getKey()).isEqualTo(RESOURCE_KEY)); +// +// final PagedQueryResult inventoryEntryQueryResult = +// targetClient +// .execute( +// InventoryEntryQuery.of() +// .withPredicates(QueryPredicate.of(format("sku=\"%s\"", RESOURCE_KEY)))) +// .toCompletableFuture() +// .join(); +// +// assertThat(inventoryEntryQueryResult.getResults()) +// .hasSize(1) +// .singleElement() +// .satisfies(inventoryEntry -> assertThat(inventoryEntry.getSku()).isEqualTo(RESOURCE_KEY)); +// +// final PagedQueryResult cartDiscountPagedQueryResult = +// targetClient +// .execute( +// CartDiscountQuery.of() +// .withPredicates(queryModel -> queryModel.key().is(RESOURCE_KEY))) +// .toCompletableFuture() +// .join(); +// +// assertThat(cartDiscountPagedQueryResult.getResults()) +// .hasSize(1) +// .singleElement() +// .satisfies(cartDiscount -> assertThat(cartDiscount.getKey()).isEqualTo(RESOURCE_KEY)); +// +// final PagedQueryResult statePagedQueryResult = +// targetClient +// .execute( +// StateQuery.of().withPredicates(queryModel -> queryModel.key().is(RESOURCE_KEY))) +// .toCompletableFuture() +// .join(); +// +// assertThat(statePagedQueryResult.getResults()) +// .hasSize(1) +// .singleElement() +// .satisfies(state -> assertThat(state.getKey()).isEqualTo(RESOURCE_KEY)); +// +// final PagedQueryResult> customObjectPagedQueryResult = +// targetClient +// .execute( +// CustomObjectQuery.ofJsonNode() +// .withPredicates( +// queryModel -> +// queryModel +// .key() +// .is(RESOURCE_KEY) +// .and(queryModel.container().is(RESOURCE_KEY)))) +// .toCompletableFuture() +// .join(); +// +// assertThat(customObjectPagedQueryResult.getResults()) +// .hasSize(1) +// .singleElement() +// .satisfies(customObject -> assertThat(customObject.getKey()).isEqualTo(RESOURCE_KEY)); +// +// final PagedQueryResult customerPagedQueryResult = +// targetClient +// .execute( +// CustomerQuery.of().withPredicates(queryModel -> +// queryModel.key().is(RESOURCE_KEY))) +// .toCompletableFuture() +// .join(); +// assertThat(customerPagedQueryResult.getResults()).hasSize(1); +// +// final PagedQueryResult shoppingListPagedQueryResult = +// targetClient +// .execute( +// ShoppingListQuery.of() +// .withPredicates(queryModel -> queryModel.key().is(RESOURCE_KEY))) +// .toCompletableFuture() +// .join(); +// assertThat(shoppingListPagedQueryResult.getResults()).hasSize(1); +// } +// +// public static void assertAllSyncersLoggingEvents(final int numberOfResources) { +// +// assertThat(cliRunnerTestLogger.getAllLoggingEvents()) +// .allMatch(loggingEvent -> !Level.ERROR.equals(loggingEvent.getLevel())); +// +// assertTypeSyncerLoggingEvents(typeSyncerTestLogger, numberOfResources); +// assertProductTypeSyncerLoggingEvents(productTypeSyncerTestLogger, numberOfResources); +// assertCategorySyncerLoggingEvents(categorySyncerTestLogger, numberOfResources); +// assertProductSyncerLoggingEvents(productSyncerTestLogger, numberOfResources); +// assertInventoryEntrySyncerLoggingEvents(inventoryEntrySyncerTestLogger, numberOfResources); +// assertCartDiscountSyncerLoggingEvents(cartDiscountSyncerTestLogger, numberOfResources); +// // +1 state is a built-in state and it cant be deleted +// assertStateSyncerLoggingEvents(stateSyncerTestLogger, numberOfResources + 1); +// assertTaxCategorySyncerLoggingEvents(taxCategorySyncerTestLogger, numberOfResources); +// assertCustomerSyncerLoggingEvents(customerSyncerTestLogger, numberOfResources); +// assertShoppingListSyncerLoggingEvents(shoppingListSyncerTestLogger, numberOfResources); +// +// // Every sync module is expected to have 2 logs (start and stats summary) +// assertThat(typeSyncerTestLogger.getAllLoggingEvents()).hasSize(2); +// assertThat(productTypeSyncerTestLogger.getAllLoggingEvents()).hasSize(2); +// assertThat(categorySyncerTestLogger.getAllLoggingEvents()).hasSize(2); +// assertThat(productSyncerTestLogger.getAllLoggingEvents()).hasSize(2); +// assertThat(inventoryEntrySyncerTestLogger.getAllLoggingEvents()).hasSize(2); +// assertThat(cartDiscountSyncerTestLogger.getAllLoggingEvents()).hasSize(2); +// assertThat(stateSyncerTestLogger.getAllLoggingEvents()).hasSize(2); +// assertThat(taxCategorySyncerTestLogger.getAllLoggingEvents()).hasSize(2); +// assertThat(customObjectSyncerTestLogger.getAllLoggingEvents()).hasSize(2); +// assertThat(customerSyncerTestLogger.getAllLoggingEvents()).hasSize(2); +// assertThat(shoppingListSyncerTestLogger.getAllLoggingEvents()).hasSize(2); +// } +// } diff --git a/src/integration-test/java/com/commercetools/project/sync/InventorySyncMultiChannelIT.java b/src/integration-test/java/com/commercetools/project/sync/InventorySyncMultiChannelIT.java index 5ab9d2c7..016efbd4 100644 --- a/src/integration-test/java/com/commercetools/project/sync/InventorySyncMultiChannelIT.java +++ b/src/integration-test/java/com/commercetools/project/sync/InventorySyncMultiChannelIT.java @@ -1,206 +1,206 @@ -package com.commercetools.project.sync; - -import static com.commercetools.project.sync.util.CtpClientUtils.CTP_SOURCE_CLIENT; -import static com.commercetools.project.sync.util.CtpClientUtils.CTP_TARGET_CLIENT; -import static com.commercetools.project.sync.util.IntegrationTestUtils.cleanUpProjects; -import static com.commercetools.project.sync.util.IntegrationTestUtils.createITSyncerFactory; -import static java.util.Collections.singletonList; -import static org.assertj.core.api.Assertions.assertThat; - -import com.commercetools.project.sync.inventoryentry.InventoryEntrySyncer; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.JsonNodeFactory; -import io.sphere.sdk.channels.Channel; -import io.sphere.sdk.channels.ChannelDraft; -import io.sphere.sdk.channels.ChannelRole; -import io.sphere.sdk.channels.commands.ChannelCreateCommand; -import io.sphere.sdk.client.SphereClient; -import io.sphere.sdk.inventory.InventoryEntry; -import io.sphere.sdk.inventory.InventoryEntryDraft; -import io.sphere.sdk.inventory.InventoryEntryDraftBuilder; -import io.sphere.sdk.inventory.commands.InventoryEntryCreateCommand; -import io.sphere.sdk.models.LocalizedString; -import io.sphere.sdk.models.Reference; -import io.sphere.sdk.types.CustomFieldsDraft; -import io.sphere.sdk.types.FieldDefinition; -import io.sphere.sdk.types.StringFieldType; -import io.sphere.sdk.types.TypeDraft; -import io.sphere.sdk.types.TypeDraftBuilder; -import io.sphere.sdk.types.commands.TypeCreateCommand; -import java.util.Collections; -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; -import java.util.concurrent.CompletableFuture; -import java.util.stream.IntStream; -import javax.annotation.Nonnull; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import uk.org.lidalia.slf4jext.Level; -import uk.org.lidalia.slf4jtest.TestLogger; -import uk.org.lidalia.slf4jtest.TestLoggerFactory; - -@Disabled( - "Disabled for normal builds, " - + "This scenario created to evaluate multiple channel use case" - + "see: https://github.com/commercetools/commercetools-project-sync/issues/301") -public class InventorySyncMultiChannelIT { - private static final TestLogger testLogger = - TestLoggerFactory.getTestLogger(InventoryEntrySyncer.class); - - public static final String SKU_1 = "SKU_ONE"; - public static final String SKU_2 = "SKU_TWO"; - public static final String SUPPLY_CHANNEL_KEY_1 = "channel-key_1"; - public static final String SUPPLY_CHANNEL_KEY_2 = "channel-key_2"; - - public static final String CUSTOM_TYPE = "inventory-custom-type-name"; - public static final String CUSTOM_FIELD_NAME = "inventory-custom-field-1"; - - @BeforeEach - void setup() { - testLogger.clearAll(); - cleanUpProjects(CTP_SOURCE_CLIENT, CTP_TARGET_CLIENT); - create249InventoryEntry(CTP_SOURCE_CLIENT); - create249InventoryEntry(CTP_TARGET_CLIENT); - setupProjectData(CTP_SOURCE_CLIENT); - setupProjectData(CTP_TARGET_CLIENT); - } - - private void setupProjectData(SphereClient sphereClient) { - final ChannelDraft channelDraft1 = - ChannelDraft.of(SUPPLY_CHANNEL_KEY_1).withRoles(ChannelRole.INVENTORY_SUPPLY); - final ChannelDraft channelDraft2 = - ChannelDraft.of(SUPPLY_CHANNEL_KEY_2).withRoles(ChannelRole.INVENTORY_SUPPLY); - - final String channelId1 = - sphereClient - .execute(ChannelCreateCommand.of(channelDraft1)) - .toCompletableFuture() - .join() - .getId(); - final String channelId2 = - sphereClient - .execute(ChannelCreateCommand.of(channelDraft2)) - .toCompletableFuture() - .join() - .getId(); - - final Reference supplyChannelReference1 = Channel.referenceOfId(channelId1); - final Reference supplyChannelReference2 = Channel.referenceOfId(channelId2); - - createInventoriesCustomType(sphereClient); - - // NOTE: There can only be one inventory entry for the combination of sku and supplyChannel. - final InventoryEntryDraft draft1 = InventoryEntryDraftBuilder.of(SKU_1, 0L).build(); - final InventoryEntryDraft draft2 = - InventoryEntryDraftBuilder.of(SKU_1, 0L) - .supplyChannel(supplyChannelReference1) - .custom(CustomFieldsDraft.ofTypeKeyAndJson(CUSTOM_TYPE, getMockCustomFieldsJsons())) - .build(); - final InventoryEntryDraft draft3 = - InventoryEntryDraftBuilder.of(SKU_1, 1L) - .supplyChannel(supplyChannelReference2) - .custom(CustomFieldsDraft.ofTypeKeyAndJson(CUSTOM_TYPE, getMockCustomFieldsJsons())) - .build(); - - final InventoryEntryDraft draft4 = InventoryEntryDraftBuilder.of(SKU_2, 0L).build(); - final InventoryEntryDraft draft5 = - InventoryEntryDraftBuilder.of(SKU_2, 0L) - .supplyChannel(supplyChannelReference1) - .custom(CustomFieldsDraft.ofTypeKeyAndJson(CUSTOM_TYPE, getMockCustomFieldsJsons())) - .build(); - final InventoryEntryDraft draft6 = - InventoryEntryDraftBuilder.of(SKU_2, 1L) - .supplyChannel(supplyChannelReference2) - .custom(CustomFieldsDraft.ofTypeKeyAndJson(CUSTOM_TYPE, getMockCustomFieldsJsons())) - .build(); - - CompletableFuture.allOf( - sphereClient.execute(InventoryEntryCreateCommand.of(draft1)).toCompletableFuture(), - sphereClient.execute(InventoryEntryCreateCommand.of(draft2)).toCompletableFuture(), - sphereClient.execute(InventoryEntryCreateCommand.of(draft3)).toCompletableFuture(), - sphereClient.execute(InventoryEntryCreateCommand.of(draft4)).toCompletableFuture(), - sphereClient.execute(InventoryEntryCreateCommand.of(draft5)).toCompletableFuture(), - sphereClient.execute(InventoryEntryCreateCommand.of(draft6)).toCompletableFuture()) - .join(); - } - - private static void createInventoriesCustomType(@Nonnull final SphereClient ctpClient) { - final FieldDefinition fieldDefinition = - FieldDefinition.of( - StringFieldType.of(), - CUSTOM_FIELD_NAME, - LocalizedString.of(Locale.ENGLISH, CUSTOM_FIELD_NAME), - false); - final TypeDraft typeDraft = - TypeDraftBuilder.of( - CUSTOM_TYPE, - LocalizedString.of(Locale.ENGLISH, CUSTOM_TYPE), - Collections.singleton(InventoryEntry.resourceTypeId())) - .fieldDefinitions(singletonList(fieldDefinition)) - .build(); - ctpClient.execute(TypeCreateCommand.of(typeDraft)).toCompletableFuture().join(); - } - - private static Map getMockCustomFieldsJsons() { - final Map customFieldsJsons = new HashMap<>(); - customFieldsJsons.put(CUSTOM_FIELD_NAME, JsonNodeFactory.instance.textNode("customValue")); - return customFieldsJsons; - } - - private void create249InventoryEntry(SphereClient sphereClient) { - CompletableFuture.allOf( - IntStream.range(0, 10) - .mapToObj( - value -> - sphereClient - .execute( - InventoryEntryCreateCommand.of( - InventoryEntryDraftBuilder.of("SKU_" + value, 1L).build())) - .toCompletableFuture()) - .toArray(CompletableFuture[]::new)) - .join(); - - CompletableFuture.allOf( - IntStream.range(0, 251) - .mapToObj(value -> create(sphereClient, value)) - .toArray(CompletableFuture[]::new)) - .join(); - } - - private CompletableFuture create(SphereClient sphereClient, int value) { - final ChannelDraft channelDraft1 = - ChannelDraft.of("other-channel-key_" + value).withRoles(ChannelRole.INVENTORY_SUPPLY); - - final String channelId = - sphereClient - .execute(ChannelCreateCommand.of(channelDraft1)) - .toCompletableFuture() - .join() - .getId(); - - final Reference supplyChannelReference = Channel.referenceOfId(channelId); - - return sphereClient - .execute( - InventoryEntryCreateCommand.of( - InventoryEntryDraftBuilder.of("SKU_CHANNEL", 0L) - .supplyChannel(supplyChannelReference) - .build())) - .toCompletableFuture(); - } - - @Test - void run_asInventoryFullSync_ShouldNotReturnAnError() { - // test - CliRunner.of().run(new String[] {"-s", "inventoryEntries", "-f"}, createITSyncerFactory()); - - // assertions - assertThat(testLogger.getAllLoggingEvents()) - .allMatch(loggingEvent -> !Level.ERROR.equals(loggingEvent.getLevel())); - - // Every sync module is expected to have 2 logs (start and stats summary) - assertThat(testLogger.getAllLoggingEvents()).hasSize(2); - } -} +// package com.commercetools.project.sync; +// +// import static com.commercetools.project.sync.util.CtpClientUtils.CTP_SOURCE_CLIENT; +// import static com.commercetools.project.sync.util.CtpClientUtils.CTP_TARGET_CLIENT; +// import static com.commercetools.project.sync.util.IntegrationTestUtils.cleanUpProjects; +// import static com.commercetools.project.sync.util.IntegrationTestUtils.createITSyncerFactory; +// import static java.util.Collections.singletonList; +// import static org.assertj.core.api.Assertions.assertThat; +// +// import com.commercetools.project.sync.inventoryentry.InventoryEntrySyncer; +// import com.fasterxml.jackson.databind.JsonNode; +// import com.fasterxml.jackson.databind.node.JsonNodeFactory; +// import io.sphere.sdk.channels.Channel; +// import io.sphere.sdk.channels.ChannelDraft; +// import io.sphere.sdk.channels.ChannelRole; +// import io.sphere.sdk.channels.commands.ChannelCreateCommand; +// import io.sphere.sdk.client.SphereClient; +// import io.sphere.sdk.inventory.InventoryEntry; +// import io.sphere.sdk.inventory.InventoryEntryDraft; +// import io.sphere.sdk.inventory.InventoryEntryDraftBuilder; +// import io.sphere.sdk.inventory.commands.InventoryEntryCreateCommand; +// import io.sphere.sdk.models.LocalizedString; +// import io.sphere.sdk.models.Reference; +// import io.sphere.sdk.types.CustomFieldsDraft; +// import io.sphere.sdk.types.FieldDefinition; +// import io.sphere.sdk.types.StringFieldType; +// import io.sphere.sdk.types.TypeDraft; +// import io.sphere.sdk.types.TypeDraftBuilder; +// import io.sphere.sdk.types.commands.TypeCreateCommand; +// import java.util.Collections; +// import java.util.HashMap; +// import java.util.Locale; +// import java.util.Map; +// import java.util.concurrent.CompletableFuture; +// import java.util.stream.IntStream; +// import javax.annotation.Nonnull; +// import org.junit.jupiter.api.BeforeEach; +// import org.junit.jupiter.api.Disabled; +// import org.junit.jupiter.api.Test; +// import uk.org.lidalia.slf4jext.Level; +// import uk.org.lidalia.slf4jtest.TestLogger; +// import uk.org.lidalia.slf4jtest.TestLoggerFactory; +// +// @Disabled( +// "Disabled for normal builds, " +// + "This scenario created to evaluate multiple channel use case" +// + "see: https://github.com/commercetools/commercetools-project-sync/issues/301") +// public class InventorySyncMultiChannelIT { +// private static final TestLogger testLogger = +// TestLoggerFactory.getTestLogger(InventoryEntrySyncer.class); +// +// public static final String SKU_1 = "SKU_ONE"; +// public static final String SKU_2 = "SKU_TWO"; +// public static final String SUPPLY_CHANNEL_KEY_1 = "channel-key_1"; +// public static final String SUPPLY_CHANNEL_KEY_2 = "channel-key_2"; +// +// public static final String CUSTOM_TYPE = "inventory-custom-type-name"; +// public static final String CUSTOM_FIELD_NAME = "inventory-custom-field-1"; +// +// @BeforeEach +// void setup() { +// testLogger.clearAll(); +// cleanUpProjects(CTP_SOURCE_CLIENT, CTP_TARGET_CLIENT); +// create249InventoryEntry(CTP_SOURCE_CLIENT); +// create249InventoryEntry(CTP_TARGET_CLIENT); +// setupProjectData(CTP_SOURCE_CLIENT); +// setupProjectData(CTP_TARGET_CLIENT); +// } +// +// private void setupProjectData(SphereClient sphereClient) { +// final ChannelDraft channelDraft1 = +// ChannelDraft.of(SUPPLY_CHANNEL_KEY_1).withRoles(ChannelRole.INVENTORY_SUPPLY); +// final ChannelDraft channelDraft2 = +// ChannelDraft.of(SUPPLY_CHANNEL_KEY_2).withRoles(ChannelRole.INVENTORY_SUPPLY); +// +// final String channelId1 = +// sphereClient +// .execute(ChannelCreateCommand.of(channelDraft1)) +// .toCompletableFuture() +// .join() +// .getId(); +// final String channelId2 = +// sphereClient +// .execute(ChannelCreateCommand.of(channelDraft2)) +// .toCompletableFuture() +// .join() +// .getId(); +// +// final Reference supplyChannelReference1 = Channel.referenceOfId(channelId1); +// final Reference supplyChannelReference2 = Channel.referenceOfId(channelId2); +// +// createInventoriesCustomType(sphereClient); +// +// // NOTE: There can only be one inventory entry for the combination of sku and supplyChannel. +// final InventoryEntryDraft draft1 = InventoryEntryDraftBuilder.of(SKU_1, 0L).build(); +// final InventoryEntryDraft draft2 = +// InventoryEntryDraftBuilder.of(SKU_1, 0L) +// .supplyChannel(supplyChannelReference1) +// .custom(CustomFieldsDraft.ofTypeKeyAndJson(CUSTOM_TYPE, getMockCustomFieldsJsons())) +// .build(); +// final InventoryEntryDraft draft3 = +// InventoryEntryDraftBuilder.of(SKU_1, 1L) +// .supplyChannel(supplyChannelReference2) +// .custom(CustomFieldsDraft.ofTypeKeyAndJson(CUSTOM_TYPE, getMockCustomFieldsJsons())) +// .build(); +// +// final InventoryEntryDraft draft4 = InventoryEntryDraftBuilder.of(SKU_2, 0L).build(); +// final InventoryEntryDraft draft5 = +// InventoryEntryDraftBuilder.of(SKU_2, 0L) +// .supplyChannel(supplyChannelReference1) +// .custom(CustomFieldsDraft.ofTypeKeyAndJson(CUSTOM_TYPE, getMockCustomFieldsJsons())) +// .build(); +// final InventoryEntryDraft draft6 = +// InventoryEntryDraftBuilder.of(SKU_2, 1L) +// .supplyChannel(supplyChannelReference2) +// .custom(CustomFieldsDraft.ofTypeKeyAndJson(CUSTOM_TYPE, getMockCustomFieldsJsons())) +// .build(); +// +// CompletableFuture.allOf( +// sphereClient.execute(InventoryEntryCreateCommand.of(draft1)).toCompletableFuture(), +// sphereClient.execute(InventoryEntryCreateCommand.of(draft2)).toCompletableFuture(), +// sphereClient.execute(InventoryEntryCreateCommand.of(draft3)).toCompletableFuture(), +// sphereClient.execute(InventoryEntryCreateCommand.of(draft4)).toCompletableFuture(), +// sphereClient.execute(InventoryEntryCreateCommand.of(draft5)).toCompletableFuture(), +// sphereClient.execute(InventoryEntryCreateCommand.of(draft6)).toCompletableFuture()) +// .join(); +// } +// +// private static void createInventoriesCustomType(@Nonnull final SphereClient ctpClient) { +// final FieldDefinition fieldDefinition = +// FieldDefinition.of( +// StringFieldType.of(), +// CUSTOM_FIELD_NAME, +// LocalizedString.of(Locale.ENGLISH, CUSTOM_FIELD_NAME), +// false); +// final TypeDraft typeDraft = +// TypeDraftBuilder.of( +// CUSTOM_TYPE, +// LocalizedString.of(Locale.ENGLISH, CUSTOM_TYPE), +// Collections.singleton(InventoryEntry.resourceTypeId())) +// .fieldDefinitions(singletonList(fieldDefinition)) +// .build(); +// ctpClient.execute(TypeCreateCommand.of(typeDraft)).toCompletableFuture().join(); +// } +// +// private static Map getMockCustomFieldsJsons() { +// final Map customFieldsJsons = new HashMap<>(); +// customFieldsJsons.put(CUSTOM_FIELD_NAME, JsonNodeFactory.instance.textNode("customValue")); +// return customFieldsJsons; +// } +// +// private void create249InventoryEntry(SphereClient sphereClient) { +// CompletableFuture.allOf( +// IntStream.range(0, 10) +// .mapToObj( +// value -> +// sphereClient +// .execute( +// InventoryEntryCreateCommand.of( +// InventoryEntryDraftBuilder.of("SKU_" + value, 1L).build())) +// .toCompletableFuture()) +// .toArray(CompletableFuture[]::new)) +// .join(); +// +// CompletableFuture.allOf( +// IntStream.range(0, 251) +// .mapToObj(value -> create(sphereClient, value)) +// .toArray(CompletableFuture[]::new)) +// .join(); +// } +// +// private CompletableFuture create(SphereClient sphereClient, int value) { +// final ChannelDraft channelDraft1 = +// ChannelDraft.of("other-channel-key_" + value).withRoles(ChannelRole.INVENTORY_SUPPLY); +// +// final String channelId = +// sphereClient +// .execute(ChannelCreateCommand.of(channelDraft1)) +// .toCompletableFuture() +// .join() +// .getId(); +// +// final Reference supplyChannelReference = Channel.referenceOfId(channelId); +// +// return sphereClient +// .execute( +// InventoryEntryCreateCommand.of( +// InventoryEntryDraftBuilder.of("SKU_CHANNEL", 0L) +// .supplyChannel(supplyChannelReference) +// .build())) +// .toCompletableFuture(); +// } +// +// @Test +// void run_asInventoryFullSync_ShouldNotReturnAnError() { +// // test +// CliRunner.of().run(new String[] {"-s", "inventoryEntries", "-f"}, createITSyncerFactory()); +// +// // assertions +// assertThat(testLogger.getAllLoggingEvents()) +// .allMatch(loggingEvent -> !Level.ERROR.equals(loggingEvent.getLevel())); +// +// // Every sync module is expected to have 2 logs (start and stats summary) +// assertThat(testLogger.getAllLoggingEvents()).hasSize(2); +// } +// } diff --git a/src/integration-test/java/com/commercetools/project/sync/ProductSyncWithDiscountedPrice.java b/src/integration-test/java/com/commercetools/project/sync/ProductSyncWithDiscountedPrice.java index bfae1407..1112c017 100644 --- a/src/integration-test/java/com/commercetools/project/sync/ProductSyncWithDiscountedPrice.java +++ b/src/integration-test/java/com/commercetools/project/sync/ProductSyncWithDiscountedPrice.java @@ -1,177 +1,179 @@ -package com.commercetools.project.sync; - -import static com.commercetools.project.sync.util.CtpClientUtils.CTP_SOURCE_CLIENT; -import static com.commercetools.project.sync.util.CtpClientUtils.CTP_TARGET_CLIENT; -import static com.commercetools.project.sync.util.IntegrationTestUtils.cleanUpProjects; -import static com.commercetools.project.sync.util.IntegrationTestUtils.createITSyncerFactory; -import static com.neovisionaries.i18n.CountryCode.DE; -import static io.sphere.sdk.models.DefaultCurrencyUnits.EUR; -import static io.sphere.sdk.models.LocalizedString.ofEnglish; -import static java.util.Collections.emptyList; -import static org.assertj.core.api.Assertions.assertThat; - -import com.neovisionaries.i18n.CountryCode; -import io.sphere.sdk.client.SphereClient; -import io.sphere.sdk.models.Reference; -import io.sphere.sdk.productdiscounts.DiscountedPrice; -import io.sphere.sdk.productdiscounts.ProductDiscount; -import io.sphere.sdk.productdiscounts.ProductDiscountDraft; -import io.sphere.sdk.productdiscounts.ProductDiscountDraftBuilder; -import io.sphere.sdk.productdiscounts.ProductDiscountValue; -import io.sphere.sdk.productdiscounts.commands.ProductDiscountCreateCommand; -import io.sphere.sdk.products.Price; -import io.sphere.sdk.products.PriceDraft; -import io.sphere.sdk.products.PriceDraftBuilder; -import io.sphere.sdk.products.Product; -import io.sphere.sdk.products.ProductDraft; -import io.sphere.sdk.products.ProductDraftBuilder; -import io.sphere.sdk.products.ProductVariant; -import io.sphere.sdk.products.ProductVariantDraft; -import io.sphere.sdk.products.ProductVariantDraftBuilder; -import io.sphere.sdk.products.commands.ProductCreateCommand; -import io.sphere.sdk.products.queries.ProductQuery; -import io.sphere.sdk.producttypes.ProductType; -import io.sphere.sdk.producttypes.ProductTypeDraft; -import io.sphere.sdk.producttypes.ProductTypeDraftBuilder; -import io.sphere.sdk.producttypes.commands.ProductTypeCreateCommand; -import io.sphere.sdk.queries.PagedQueryResult; -import java.math.BigDecimal; -import java.time.ZonedDateTime; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import javax.money.CurrencyUnit; -import org.javamoney.moneta.FastMoney; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import uk.org.lidalia.slf4jext.Level; -import uk.org.lidalia.slf4jtest.TestLogger; -import uk.org.lidalia.slf4jtest.TestLoggerFactory; - -// This will suppress MoreThanOneLogger warnings in this class -@SuppressWarnings("PMD.MoreThanOneLogger") -class ProductSyncWithDiscountedPrice { - private static final TestLogger cliRunnerTestLogger = - TestLoggerFactory.getTestLogger(CliRunner.class); - - private static final String MAIN_PRODUCT_TYPE_KEY = "main-product-type"; - private static final String MAIN_PRODUCT_MASTER_VARIANT_KEY = "main-product-master-variant-key"; - private static final String MAIN_PRODUCT_KEY = "product-with-references"; - private static final FastMoney TEN_EUR = FastMoney.of(10, EUR); - - @BeforeEach - void setup() { - cliRunnerTestLogger.clearAll(); - - ProductDiscountDraft productDiscountDraft = - ProductDiscountDraftBuilder.of() - .value(ProductDiscountValue.ofExternal()) - .name(ofEnglish("testProductDiscount")) - .predicate("1=1") - .sortOrder("0.9") - .isActive(true) - .build(); - ProductDiscount productDiscount = - CTP_TARGET_CLIENT - .execute(ProductDiscountCreateCommand.of(productDiscountDraft)) - .toCompletableFuture() - .join(); - setupProjectData(CTP_SOURCE_CLIENT, null); - setupProjectData(CTP_TARGET_CLIENT, productDiscount.getId()); - } - - static void setupProjectData(@Nonnull final SphereClient sphereClient, String productDiscountId) { - final ProductTypeDraft productTypeDraft = - ProductTypeDraftBuilder.of( - MAIN_PRODUCT_TYPE_KEY, - MAIN_PRODUCT_TYPE_KEY, - "a productType for t-shirts", - emptyList()) - .build(); - - final ProductType productType = - sphereClient - .execute(ProductTypeCreateCommand.of(productTypeDraft)) - .toCompletableFuture() - .join(); - - final PriceDraft priceDraft = - PriceDraftBuilder.of( - getPriceDraft(BigDecimal.valueOf(222), EUR, DE, null, null, productDiscountId)) - .build(); - - final ProductVariantDraft masterVariant = - ProductVariantDraftBuilder.of() - .key(MAIN_PRODUCT_MASTER_VARIANT_KEY) - .sku(MAIN_PRODUCT_MASTER_VARIANT_KEY) - .prices(priceDraft) - .build(); - - final ProductDraft draft = - ProductDraftBuilder.of( - productType, - ofEnglish(MAIN_PRODUCT_KEY), - ofEnglish(MAIN_PRODUCT_KEY), - masterVariant) - .key(MAIN_PRODUCT_KEY) - .build(); - - sphereClient.execute(ProductCreateCommand.of(draft)).toCompletableFuture().join(); - } - - @AfterAll - static void tearDownSuite() { - cleanUpProjects(CTP_SOURCE_CLIENT, CTP_TARGET_CLIENT); - } - - @Test - void run_WhenTargetProductHasDiscountedPrice_ShouldNotRemoveIt() { - // test - CliRunner.of() - .run(new String[] {"-s", "products", "-r", "runnerName", "-f"}, createITSyncerFactory()); - - // assertions - assertThat(cliRunnerTestLogger.getAllLoggingEvents()) - .allMatch(loggingEvent -> !Level.ERROR.equals(loggingEvent.getLevel())); - - final PagedQueryResult productQueryResult = - CTP_TARGET_CLIENT.execute(ProductQuery.of()).toCompletableFuture().join(); - - assertThat(productQueryResult.getResults()) - .hasSize(1) - .singleElement() - .satisfies( - product -> { - final ProductVariant stagedMasterVariant = - product.getMasterData().getStaged().getMasterVariant(); - assertThat(stagedMasterVariant.getPrices()) - .satisfies( - prices -> { - Price price = prices.get(0); - assertThat(price.getDiscounted()).isNotNull(); - assertThat(price.getDiscounted().getValue()).isEqualTo(TEN_EUR); - }); - }); - } - - @Nonnull - public static PriceDraft getPriceDraft( - @Nonnull final BigDecimal value, - @Nonnull final CurrencyUnit currencyUnits, - @Nullable final CountryCode countryCode, - @Nullable final ZonedDateTime validFrom, - @Nullable final ZonedDateTime validUntil, - @Nullable final String productDiscountReferenceId) { - DiscountedPrice discounted = null; - if (productDiscountReferenceId != null) { - discounted = - DiscountedPrice.of(TEN_EUR, Reference.of("product-discount", productDiscountReferenceId)); - } - return PriceDraftBuilder.of(Price.of(value, currencyUnits)) - .country(countryCode) - .validFrom(validFrom) - .validUntil(validUntil) - .discounted(discounted) - .build(); - } -} +// package com.commercetools.project.sync; +// +// import static com.commercetools.project.sync.util.CtpClientUtils.CTP_SOURCE_CLIENT; +// import static com.commercetools.project.sync.util.CtpClientUtils.CTP_TARGET_CLIENT; +// import static com.commercetools.project.sync.util.IntegrationTestUtils.cleanUpProjects; +// import static com.commercetools.project.sync.util.IntegrationTestUtils.createITSyncerFactory; +// import static com.neovisionaries.i18n.CountryCode.DE; +// import static io.sphere.sdk.models.DefaultCurrencyUnits.EUR; +// import static io.sphere.sdk.models.LocalizedString.ofEnglish; +// import static java.util.Collections.emptyList; +// import static org.assertj.core.api.Assertions.assertThat; +// +// import com.neovisionaries.i18n.CountryCode; +// import io.sphere.sdk.client.SphereClient; +// import io.sphere.sdk.models.Reference; +// import io.sphere.sdk.productdiscounts.DiscountedPrice; +// import io.sphere.sdk.productdiscounts.ProductDiscount; +// import io.sphere.sdk.productdiscounts.ProductDiscountDraft; +// import io.sphere.sdk.productdiscounts.ProductDiscountDraftBuilder; +// import io.sphere.sdk.productdiscounts.ProductDiscountValue; +// import io.sphere.sdk.productdiscounts.commands.ProductDiscountCreateCommand; +// import io.sphere.sdk.products.Price; +// import io.sphere.sdk.products.PriceDraft; +// import io.sphere.sdk.products.PriceDraftBuilder; +// import io.sphere.sdk.products.Product; +// import io.sphere.sdk.products.ProductDraft; +// import io.sphere.sdk.products.ProductDraftBuilder; +// import io.sphere.sdk.products.ProductVariant; +// import io.sphere.sdk.products.ProductVariantDraft; +// import io.sphere.sdk.products.ProductVariantDraftBuilder; +// import io.sphere.sdk.products.commands.ProductCreateCommand; +// import io.sphere.sdk.products.queries.ProductQuery; +// import io.sphere.sdk.producttypes.ProductType; +// import io.sphere.sdk.producttypes.ProductTypeDraft; +// import io.sphere.sdk.producttypes.ProductTypeDraftBuilder; +// import io.sphere.sdk.producttypes.commands.ProductTypeCreateCommand; +// import io.sphere.sdk.queries.PagedQueryResult; +// import java.math.BigDecimal; +// import java.time.ZonedDateTime; +// import javax.annotation.Nonnull; +// import javax.annotation.Nullable; +// import javax.money.CurrencyUnit; +// import org.javamoney.moneta.FastMoney; +// import org.junit.jupiter.api.AfterAll; +// import org.junit.jupiter.api.BeforeEach; +// import org.junit.jupiter.api.Test; +// import uk.org.lidalia.slf4jext.Level; +// import uk.org.lidalia.slf4jtest.TestLogger; +// import uk.org.lidalia.slf4jtest.TestLoggerFactory; +// +//// This will suppress MoreThanOneLogger warnings in this class +// @SuppressWarnings("PMD.MoreThanOneLogger") +// class ProductSyncWithDiscountedPrice { +// private static final TestLogger cliRunnerTestLogger = +// TestLoggerFactory.getTestLogger(CliRunner.class); +// +// private static final String MAIN_PRODUCT_TYPE_KEY = "main-product-type"; +// private static final String MAIN_PRODUCT_MASTER_VARIANT_KEY = "main-product-master-variant-key"; +// private static final String MAIN_PRODUCT_KEY = "product-with-references"; +// private static final FastMoney TEN_EUR = FastMoney.of(10, EUR); +// +// @BeforeEach +// void setup() { +// cliRunnerTestLogger.clearAll(); +// +// ProductDiscountDraft productDiscountDraft = +// ProductDiscountDraftBuilder.of() +// .value(ProductDiscountValue.ofExternal()) +// .name(ofEnglish("testProductDiscount")) +// .predicate("1=1") +// .sortOrder("0.9") +// .isActive(true) +// .build(); +// ProductDiscount productDiscount = +// CTP_TARGET_CLIENT +// .execute(ProductDiscountCreateCommand.of(productDiscountDraft)) +// .toCompletableFuture() +// .join(); +// setupProjectData(CTP_SOURCE_CLIENT, null); +// setupProjectData(CTP_TARGET_CLIENT, productDiscount.getId()); +// } +// +// static void setupProjectData(@Nonnull final SphereClient sphereClient, String productDiscountId) +// { +// final ProductTypeDraft productTypeDraft = +// ProductTypeDraftBuilder.of( +// MAIN_PRODUCT_TYPE_KEY, +// MAIN_PRODUCT_TYPE_KEY, +// "a productType for t-shirts", +// emptyList()) +// .build(); +// +// final ProductType productType = +// sphereClient +// .execute(ProductTypeCreateCommand.of(productTypeDraft)) +// .toCompletableFuture() +// .join(); +// +// final PriceDraft priceDraft = +// PriceDraftBuilder.of( +// getPriceDraft(BigDecimal.valueOf(222), EUR, DE, null, null, productDiscountId)) +// .build(); +// +// final ProductVariantDraft masterVariant = +// ProductVariantDraftBuilder.of() +// .key(MAIN_PRODUCT_MASTER_VARIANT_KEY) +// .sku(MAIN_PRODUCT_MASTER_VARIANT_KEY) +// .prices(priceDraft) +// .build(); +// +// final ProductDraft draft = +// ProductDraftBuilder.of( +// productType, +// ofEnglish(MAIN_PRODUCT_KEY), +// ofEnglish(MAIN_PRODUCT_KEY), +// masterVariant) +// .key(MAIN_PRODUCT_KEY) +// .build(); +// +// sphereClient.execute(ProductCreateCommand.of(draft)).toCompletableFuture().join(); +// } +// +// @AfterAll +// static void tearDownSuite() { +// cleanUpProjects(CTP_SOURCE_CLIENT, CTP_TARGET_CLIENT); +// } +// +// @Test +// void run_WhenTargetProductHasDiscountedPrice_ShouldNotRemoveIt() { +// // test +// CliRunner.of() +// .run(new String[] {"-s", "products", "-r", "runnerName", "-f"}, createITSyncerFactory()); +// +// // assertions +// assertThat(cliRunnerTestLogger.getAllLoggingEvents()) +// .allMatch(loggingEvent -> !Level.ERROR.equals(loggingEvent.getLevel())); +// +// final PagedQueryResult productQueryResult = +// CTP_TARGET_CLIENT.execute(ProductQuery.of()).toCompletableFuture().join(); +// +// assertThat(productQueryResult.getResults()) +// .hasSize(1) +// .singleElement() +// .satisfies( +// product -> { +// final ProductVariant stagedMasterVariant = +// product.getMasterData().getStaged().getMasterVariant(); +// assertThat(stagedMasterVariant.getPrices()) +// .satisfies( +// prices -> { +// Price price = prices.get(0); +// assertThat(price.getDiscounted()).isNotNull(); +// assertThat(price.getDiscounted().getValue()).isEqualTo(TEN_EUR); +// }); +// }); +// } +// +// @Nonnull +// public static PriceDraft getPriceDraft( +// @Nonnull final BigDecimal value, +// @Nonnull final CurrencyUnit currencyUnits, +// @Nullable final CountryCode countryCode, +// @Nullable final ZonedDateTime validFrom, +// @Nullable final ZonedDateTime validUntil, +// @Nullable final String productDiscountReferenceId) { +// DiscountedPrice discounted = null; +// if (productDiscountReferenceId != null) { +// discounted = +// DiscountedPrice.of(TEN_EUR, Reference.of("product-discount", +// productDiscountReferenceId)); +// } +// return PriceDraftBuilder.of(Price.of(value, currencyUnits)) +// .country(countryCode) +// .validFrom(validFrom) +// .validUntil(validUntil) +// .discounted(discounted) +// .build(); +// } +// } diff --git a/src/integration-test/java/com/commercetools/project/sync/ProductSyncWithMasterVariantSwitchIT.java b/src/integration-test/java/com/commercetools/project/sync/ProductSyncWithMasterVariantSwitchIT.java index 6fed98fb..711fc55b 100644 --- a/src/integration-test/java/com/commercetools/project/sync/ProductSyncWithMasterVariantSwitchIT.java +++ b/src/integration-test/java/com/commercetools/project/sync/ProductSyncWithMasterVariantSwitchIT.java @@ -1,143 +1,143 @@ -package com.commercetools.project.sync; - -import static com.commercetools.project.sync.util.CtpClientUtils.CTP_SOURCE_CLIENT; -import static com.commercetools.project.sync.util.CtpClientUtils.CTP_TARGET_CLIENT; -import static com.commercetools.project.sync.util.IntegrationTestUtils.cleanUpProjects; -import static com.commercetools.project.sync.util.IntegrationTestUtils.createITSyncerFactory; -import static io.sphere.sdk.models.LocalizedString.ofEnglish; -import static org.assertj.core.api.Assertions.assertThat; - -import io.sphere.sdk.client.SphereClient; -import io.sphere.sdk.models.LocalizedString; -import io.sphere.sdk.products.Product; -import io.sphere.sdk.products.ProductDraft; -import io.sphere.sdk.products.ProductDraftBuilder; -import io.sphere.sdk.products.ProductVariant; -import io.sphere.sdk.products.ProductVariantDraft; -import io.sphere.sdk.products.ProductVariantDraftBuilder; -import io.sphere.sdk.products.attributes.AttributeConstraint; -import io.sphere.sdk.products.attributes.AttributeDefinitionDraftBuilder; -import io.sphere.sdk.products.attributes.AttributeDraft; -import io.sphere.sdk.products.attributes.StringAttributeType; -import io.sphere.sdk.products.commands.ProductCreateCommand; -import io.sphere.sdk.products.queries.ProductQuery; -import io.sphere.sdk.producttypes.ProductType; -import io.sphere.sdk.producttypes.ProductTypeDraft; -import io.sphere.sdk.producttypes.ProductTypeDraftBuilder; -import io.sphere.sdk.producttypes.commands.ProductTypeCreateCommand; -import io.sphere.sdk.queries.PagedQueryResult; -import java.util.Collections; -import java.util.List; -import javax.annotation.Nonnull; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import uk.org.lidalia.slf4jext.Level; -import uk.org.lidalia.slf4jtest.TestLogger; -import uk.org.lidalia.slf4jtest.TestLoggerFactory; - -// This will suppress MoreThanOneLogger warnings in this class -@SuppressWarnings("PMD.MoreThanOneLogger") -class ProductSyncWithMasterVariantSwitchIT { - private static final TestLogger cliRunnerTestLogger = - TestLoggerFactory.getTestLogger(CliRunner.class); - - private static final String MAIN_PRODUCT_TYPE_KEY = "main-product-type"; - private static final String MAIN_PRODUCT_KEY = "product-with-references"; - - @BeforeEach - void setup() { - cliRunnerTestLogger.clearAll(); - - setupProjectData(CTP_SOURCE_CLIENT, "Source"); - setupProjectData(CTP_TARGET_CLIENT, "Target"); - } - - static void setupProjectData( - @Nonnull final SphereClient sphereClient, @Nonnull final String variantSuffix) { - final ProductTypeDraft productTypeDraft = - ProductTypeDraftBuilder.of( - MAIN_PRODUCT_TYPE_KEY, - MAIN_PRODUCT_TYPE_KEY, - "a productType for t-shirts", - Collections.singletonList( - AttributeDefinitionDraftBuilder.of( - StringAttributeType.of(), - "test", - LocalizedString.ofEnglish("test"), - false) - .attributeConstraint(AttributeConstraint.SAME_FOR_ALL) - .build())) - .build(); - - final ProductType productType = - sphereClient - .execute(ProductTypeCreateCommand.of(productTypeDraft)) - .toCompletableFuture() - .join(); - - final ProductVariantDraft masterVariant = - ProductVariantDraftBuilder.of() - .key("key" + variantSuffix) - .sku("sku" + variantSuffix) - .attributes(AttributeDraft.of("test", "test" + variantSuffix)) - .build(); - - final ProductVariantDraft variant1 = - ProductVariantDraftBuilder.of() - .key("key" + variantSuffix + "Variant1") - .sku("sku" + variantSuffix + "Variant1") - .attributes(AttributeDraft.of("test", "test" + variantSuffix)) - .build(); - - final ProductDraft draft = - ProductDraftBuilder.of( - productType, - ofEnglish(MAIN_PRODUCT_KEY), - ofEnglish(MAIN_PRODUCT_KEY), - List.of(masterVariant, variant1)) - .key(MAIN_PRODUCT_KEY) - .build(); - - sphereClient.execute(ProductCreateCommand.of(draft)).toCompletableFuture().join(); - } - - @AfterAll - static void tearDownSuite() { - cleanUpProjects(CTP_SOURCE_CLIENT, CTP_TARGET_CLIENT); - } - - @Test - void run_WhenTargetProductDifferentSkusAndKeys_ShouldSyncTargetCorrectly() { - // test - CliRunner.of() - .run(new String[] {"-s", "products", "-r", "runnerName", "-f"}, createITSyncerFactory()); - - // assertions - assertThat(cliRunnerTestLogger.getAllLoggingEvents()) - .allMatch(loggingEvent -> !Level.ERROR.equals(loggingEvent.getLevel())); - - final PagedQueryResult productQueryResult = - CTP_TARGET_CLIENT.execute(ProductQuery.of()).toCompletableFuture().join(); - - assertThat(productQueryResult.getResults()) - .hasSize(1) - .singleElement() - .satisfies( - product -> { - final ProductVariant targetMasterVariant = - product.getMasterData().getStaged().getMasterVariant(); - final ProductVariant targetVariant1 = - product.getMasterData().getStaged().getVariants().get(0); - assertThat(targetMasterVariant.getSku()).isEqualTo("skuSource"); - assertThat(targetMasterVariant.getKey()).isEqualTo("keySource"); - assertThat(targetMasterVariant.getAttributes().get(0).getValueAsString()) - .isEqualTo("testSource"); - - assertThat(targetVariant1.getSku()).isEqualTo("skuSourceVariant1"); - assertThat(targetVariant1.getKey()).isEqualTo("keySourceVariant1"); - assertThat(targetVariant1.getAttributes().get(0).getValueAsString()) - .isEqualTo("testSource"); - }); - } -} +// package com.commercetools.project.sync; +// +// import static com.commercetools.project.sync.util.CtpClientUtils.CTP_SOURCE_CLIENT; +// import static com.commercetools.project.sync.util.CtpClientUtils.CTP_TARGET_CLIENT; +// import static com.commercetools.project.sync.util.IntegrationTestUtils.cleanUpProjects; +// import static com.commercetools.project.sync.util.IntegrationTestUtils.createITSyncerFactory; +// import static io.sphere.sdk.models.LocalizedString.ofEnglish; +// import static org.assertj.core.api.Assertions.assertThat; +// +// import io.sphere.sdk.client.SphereClient; +// import io.sphere.sdk.models.LocalizedString; +// import io.sphere.sdk.products.Product; +// import io.sphere.sdk.products.ProductDraft; +// import io.sphere.sdk.products.ProductDraftBuilder; +// import io.sphere.sdk.products.ProductVariant; +// import io.sphere.sdk.products.ProductVariantDraft; +// import io.sphere.sdk.products.ProductVariantDraftBuilder; +// import io.sphere.sdk.products.attributes.AttributeConstraint; +// import io.sphere.sdk.products.attributes.AttributeDefinitionDraftBuilder; +// import io.sphere.sdk.products.attributes.AttributeDraft; +// import io.sphere.sdk.products.attributes.StringAttributeType; +// import io.sphere.sdk.products.commands.ProductCreateCommand; +// import io.sphere.sdk.products.queries.ProductQuery; +// import io.sphere.sdk.producttypes.ProductType; +// import io.sphere.sdk.producttypes.ProductTypeDraft; +// import io.sphere.sdk.producttypes.ProductTypeDraftBuilder; +// import io.sphere.sdk.producttypes.commands.ProductTypeCreateCommand; +// import io.sphere.sdk.queries.PagedQueryResult; +// import java.util.Collections; +// import java.util.List; +// import javax.annotation.Nonnull; +// import org.junit.jupiter.api.AfterAll; +// import org.junit.jupiter.api.BeforeEach; +// import org.junit.jupiter.api.Test; +// import uk.org.lidalia.slf4jext.Level; +// import uk.org.lidalia.slf4jtest.TestLogger; +// import uk.org.lidalia.slf4jtest.TestLoggerFactory; +// +//// This will suppress MoreThanOneLogger warnings in this class +// @SuppressWarnings("PMD.MoreThanOneLogger") +// class ProductSyncWithMasterVariantSwitchIT { +// private static final TestLogger cliRunnerTestLogger = +// TestLoggerFactory.getTestLogger(CliRunner.class); +// +// private static final String MAIN_PRODUCT_TYPE_KEY = "main-product-type"; +// private static final String MAIN_PRODUCT_KEY = "product-with-references"; +// +// @BeforeEach +// void setup() { +// cliRunnerTestLogger.clearAll(); +// +// setupProjectData(CTP_SOURCE_CLIENT, "Source"); +// setupProjectData(CTP_TARGET_CLIENT, "Target"); +// } +// +// static void setupProjectData( +// @Nonnull final SphereClient sphereClient, @Nonnull final String variantSuffix) { +// final ProductTypeDraft productTypeDraft = +// ProductTypeDraftBuilder.of( +// MAIN_PRODUCT_TYPE_KEY, +// MAIN_PRODUCT_TYPE_KEY, +// "a productType for t-shirts", +// Collections.singletonList( +// AttributeDefinitionDraftBuilder.of( +// StringAttributeType.of(), +// "test", +// LocalizedString.ofEnglish("test"), +// false) +// .attributeConstraint(AttributeConstraint.SAME_FOR_ALL) +// .build())) +// .build(); +// +// final ProductType productType = +// sphereClient +// .execute(ProductTypeCreateCommand.of(productTypeDraft)) +// .toCompletableFuture() +// .join(); +// +// final ProductVariantDraft masterVariant = +// ProductVariantDraftBuilder.of() +// .key("key" + variantSuffix) +// .sku("sku" + variantSuffix) +// .attributes(AttributeDraft.of("test", "test" + variantSuffix)) +// .build(); +// +// final ProductVariantDraft variant1 = +// ProductVariantDraftBuilder.of() +// .key("key" + variantSuffix + "Variant1") +// .sku("sku" + variantSuffix + "Variant1") +// .attributes(AttributeDraft.of("test", "test" + variantSuffix)) +// .build(); +// +// final ProductDraft draft = +// ProductDraftBuilder.of( +// productType, +// ofEnglish(MAIN_PRODUCT_KEY), +// ofEnglish(MAIN_PRODUCT_KEY), +// List.of(masterVariant, variant1)) +// .key(MAIN_PRODUCT_KEY) +// .build(); +// +// sphereClient.execute(ProductCreateCommand.of(draft)).toCompletableFuture().join(); +// } +// +// @AfterAll +// static void tearDownSuite() { +// cleanUpProjects(CTP_SOURCE_CLIENT, CTP_TARGET_CLIENT); +// } +// +// @Test +// void run_WhenTargetProductDifferentSkusAndKeys_ShouldSyncTargetCorrectly() { +// // test +// CliRunner.of() +// .run(new String[] {"-s", "products", "-r", "runnerName", "-f"}, createITSyncerFactory()); +// +// // assertions +// assertThat(cliRunnerTestLogger.getAllLoggingEvents()) +// .allMatch(loggingEvent -> !Level.ERROR.equals(loggingEvent.getLevel())); +// +// final PagedQueryResult productQueryResult = +// CTP_TARGET_CLIENT.execute(ProductQuery.of()).toCompletableFuture().join(); +// +// assertThat(productQueryResult.getResults()) +// .hasSize(1) +// .singleElement() +// .satisfies( +// product -> { +// final ProductVariant targetMasterVariant = +// product.getMasterData().getStaged().getMasterVariant(); +// final ProductVariant targetVariant1 = +// product.getMasterData().getStaged().getVariants().get(0); +// assertThat(targetMasterVariant.getSku()).isEqualTo("skuSource"); +// assertThat(targetMasterVariant.getKey()).isEqualTo("keySource"); +// assertThat(targetMasterVariant.getAttributes().get(0).getValueAsString()) +// .isEqualTo("testSource"); +// +// assertThat(targetVariant1.getSku()).isEqualTo("skuSourceVariant1"); +// assertThat(targetVariant1.getKey()).isEqualTo("keySourceVariant1"); +// assertThat(targetVariant1.getAttributes().get(0).getValueAsString()) +// .isEqualTo("testSource"); +// }); +// } +// } diff --git a/src/integration-test/java/com/commercetools/project/sync/ProductSyncWithNestedReferencesIT.java b/src/integration-test/java/com/commercetools/project/sync/ProductSyncWithNestedReferencesIT.java index 62c626a9..3531fd82 100644 --- a/src/integration-test/java/com/commercetools/project/sync/ProductSyncWithNestedReferencesIT.java +++ b/src/integration-test/java/com/commercetools/project/sync/ProductSyncWithNestedReferencesIT.java @@ -1,495 +1,501 @@ -package com.commercetools.project.sync; - -import static com.commercetools.project.sync.util.CtpClientUtils.CTP_SOURCE_CLIENT; -import static com.commercetools.project.sync.util.CtpClientUtils.CTP_TARGET_CLIENT; -import static com.commercetools.project.sync.util.IntegrationTestUtils.assertCategoryExists; -import static com.commercetools.project.sync.util.IntegrationTestUtils.assertCustomerExists; -import static com.commercetools.project.sync.util.IntegrationTestUtils.assertProductTypeExists; -import static com.commercetools.project.sync.util.IntegrationTestUtils.assertStateExists; -import static com.commercetools.project.sync.util.IntegrationTestUtils.cleanUpProjects; -import static com.commercetools.project.sync.util.IntegrationTestUtils.createAttributeObject; -import static com.commercetools.project.sync.util.IntegrationTestUtils.createITSyncerFactory; -import static com.commercetools.project.sync.util.IntegrationTestUtils.createReferenceObject; -import static com.commercetools.project.sync.util.TestUtils.assertCartDiscountSyncerLoggingEvents; -import static com.commercetools.project.sync.util.TestUtils.assertCategorySyncerLoggingEvents; -import static com.commercetools.project.sync.util.TestUtils.assertCustomObjectSyncerLoggingEvents; -import static com.commercetools.project.sync.util.TestUtils.assertCustomerSyncerLoggingEvents; -import static com.commercetools.project.sync.util.TestUtils.assertInventoryEntrySyncerLoggingEvents; -import static com.commercetools.project.sync.util.TestUtils.assertProductSyncerLoggingEvents; -import static com.commercetools.project.sync.util.TestUtils.assertProductTypeSyncerLoggingEvents; -import static com.commercetools.project.sync.util.TestUtils.assertShoppingListSyncerLoggingEvents; -import static com.commercetools.project.sync.util.TestUtils.assertStateSyncerLoggingEvents; -import static com.commercetools.project.sync.util.TestUtils.assertTaxCategorySyncerLoggingEvents; -import static com.commercetools.project.sync.util.TestUtils.assertTypeSyncerLoggingEvents; -import static io.sphere.sdk.models.LocalizedString.ofEnglish; -import static java.util.Arrays.asList; -import static java.util.Collections.emptyList; -import static java.util.Collections.singletonList; -import static org.assertj.core.api.Assertions.assertThat; - -import com.commercetools.project.sync.cartdiscount.CartDiscountSyncer; -import com.commercetools.project.sync.category.CategorySyncer; -import com.commercetools.project.sync.customer.CustomerSyncer; -import com.commercetools.project.sync.customobject.CustomObjectSyncer; -import com.commercetools.project.sync.inventoryentry.InventoryEntrySyncer; -import com.commercetools.project.sync.product.ProductSyncer; -import com.commercetools.project.sync.producttype.ProductTypeSyncer; -import com.commercetools.project.sync.shoppinglist.ShoppingListSyncer; -import com.commercetools.project.sync.state.StateSyncer; -import com.commercetools.project.sync.taxcategory.TaxCategorySyncer; -import com.commercetools.project.sync.type.TypeSyncer; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.ArrayNode; -import com.fasterxml.jackson.databind.node.JsonNodeFactory; -import com.fasterxml.jackson.databind.node.ObjectNode; -import io.sphere.sdk.categories.Category; -import io.sphere.sdk.categories.CategoryDraft; -import io.sphere.sdk.categories.CategoryDraftBuilder; -import io.sphere.sdk.categories.commands.CategoryCreateCommand; -import io.sphere.sdk.client.SphereClient; -import io.sphere.sdk.customers.Customer; -import io.sphere.sdk.customers.CustomerDraft; -import io.sphere.sdk.customers.CustomerDraftBuilder; -import io.sphere.sdk.customers.CustomerSignInResult; -import io.sphere.sdk.customers.commands.CustomerCreateCommand; -import io.sphere.sdk.customobjects.CustomObject; -import io.sphere.sdk.customobjects.CustomObjectDraft; -import io.sphere.sdk.customobjects.commands.CustomObjectUpsertCommand; -import io.sphere.sdk.products.Product; -import io.sphere.sdk.products.ProductDraft; -import io.sphere.sdk.products.ProductDraftBuilder; -import io.sphere.sdk.products.ProductVariant; -import io.sphere.sdk.products.ProductVariantDraft; -import io.sphere.sdk.products.ProductVariantDraftBuilder; -import io.sphere.sdk.products.attributes.AttributeConstraint; -import io.sphere.sdk.products.attributes.AttributeDefinitionDraft; -import io.sphere.sdk.products.attributes.AttributeDefinitionDraftBuilder; -import io.sphere.sdk.products.attributes.AttributeDraft; -import io.sphere.sdk.products.attributes.NestedAttributeType; -import io.sphere.sdk.products.attributes.ReferenceAttributeType; -import io.sphere.sdk.products.attributes.SetAttributeType; -import io.sphere.sdk.products.commands.ProductCreateCommand; -import io.sphere.sdk.products.queries.ProductQuery; -import io.sphere.sdk.producttypes.ProductType; -import io.sphere.sdk.producttypes.ProductTypeDraft; -import io.sphere.sdk.producttypes.ProductTypeDraftBuilder; -import io.sphere.sdk.producttypes.commands.ProductTypeCreateCommand; -import io.sphere.sdk.queries.PagedQueryResult; -import io.sphere.sdk.states.State; -import io.sphere.sdk.states.StateDraft; -import io.sphere.sdk.states.StateDraftBuilder; -import io.sphere.sdk.states.StateType; -import io.sphere.sdk.states.commands.StateCreateCommand; -import java.util.Collections; -import javax.annotation.Nonnull; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import uk.org.lidalia.slf4jext.Level; -import uk.org.lidalia.slf4jtest.TestLogger; -import uk.org.lidalia.slf4jtest.TestLoggerFactory; - -// This will suppress MoreThanOneLogger warnings in this class -@SuppressWarnings("PMD.MoreThanOneLogger") -class ProductSyncWithNestedReferencesIT { - - private static final TestLogger cliRunnerTestLogger = - TestLoggerFactory.getTestLogger(CliRunner.class); - private static final TestLogger productSyncerTestLogger = - TestLoggerFactory.getTestLogger(ProductSyncer.class); - private static final TestLogger productTypeSyncerTestLogger = - TestLoggerFactory.getTestLogger(ProductTypeSyncer.class); - private static final TestLogger customerSyncerTestLogger = - TestLoggerFactory.getTestLogger(CustomerSyncer.class); - private static final TestLogger shoppingListSyncerTestLogger = - TestLoggerFactory.getTestLogger(ShoppingListSyncer.class); - private static final TestLogger stateSyncerTestLogger = - TestLoggerFactory.getTestLogger(StateSyncer.class); - private static final TestLogger inventoryEntrySyncerTestLogger = - TestLoggerFactory.getTestLogger(InventoryEntrySyncer.class); - private static final TestLogger customObjectSyncerTestLogger = - TestLoggerFactory.getTestLogger(CustomObjectSyncer.class); - private static final TestLogger typeSyncerTestLogger = - TestLoggerFactory.getTestLogger(TypeSyncer.class); - private static final TestLogger categorySyncerTestLogger = - TestLoggerFactory.getTestLogger(CategorySyncer.class); - private static final TestLogger cartDiscountSyncerTestLogger = - TestLoggerFactory.getTestLogger(CartDiscountSyncer.class); - private static final TestLogger taxCategorySyncerTestLogger = - TestLoggerFactory.getTestLogger(TaxCategorySyncer.class); - - private static final String INNER_PRODUCT_TYPE_KEY = "inner-product-type"; - private static final String MAIN_PRODUCT_TYPE_KEY = "sample-product-type"; - private static final String CATEGORY_KEY = "category-key"; - private static final String MAIN_PRODUCT_MASTER_VARIANT_KEY = "main-product-master-variant-key"; - private static final String MAIN_PRODUCT_KEY = "product-with-nested"; - private static final String NESTED_ATTRIBUTE_NAME = "nested-attribute"; - private static final String STATE_KEY = "state-key"; - private static final String CUSTOMER_KEY = "customer-key"; - - @BeforeEach - void setup() { - cliRunnerTestLogger.clearAll(); - productSyncerTestLogger.clearAll(); - productTypeSyncerTestLogger.clearAll(); - customerSyncerTestLogger.clearAll(); - shoppingListSyncerTestLogger.clearAll(); - stateSyncerTestLogger.clearAll(); - inventoryEntrySyncerTestLogger.clearAll(); - customObjectSyncerTestLogger.clearAll(); - typeSyncerTestLogger.clearAll(); - categorySyncerTestLogger.clearAll(); - cartDiscountSyncerTestLogger.clearAll(); - taxCategorySyncerTestLogger.clearAll(); - cleanUpProjects(CTP_SOURCE_CLIENT, CTP_TARGET_CLIENT); - setupSourceProjectData(CTP_SOURCE_CLIENT); - } - - static void setupSourceProjectData(@Nonnull final SphereClient sourceProjectClient) { - final AttributeDefinitionDraft setOfCategoriesAttributeDef = - AttributeDefinitionDraftBuilder.of( - SetAttributeType.of(ReferenceAttributeType.ofCategory()), - "categories", - ofEnglish("categories"), - false) - .searchable(false) - .attributeConstraint(AttributeConstraint.NONE) - .build(); - - final AttributeDefinitionDraft setOfProductTypeAttributeDef = - AttributeDefinitionDraftBuilder.of( - SetAttributeType.of(ReferenceAttributeType.ofProductType()), - "productTypes", - ofEnglish("productTypes"), - false) - .searchable(false) - .attributeConstraint(AttributeConstraint.NONE) - .build(); - - final AttributeDefinitionDraft setOfCustomObjectAttributeDef = - AttributeDefinitionDraftBuilder.of( - SetAttributeType.of(ReferenceAttributeType.of(CustomObject.referenceTypeId())), - "customObjects", - ofEnglish("customObjects"), - false) - .searchable(false) - .attributeConstraint(AttributeConstraint.NONE) - .build(); - - final AttributeDefinitionDraft setOfStateAttributeDef = - AttributeDefinitionDraftBuilder.of( - SetAttributeType.of(ReferenceAttributeType.of(State.referenceTypeId())), - "states", - ofEnglish("states"), - false) - .searchable(false) - .attributeConstraint(AttributeConstraint.NONE) - .build(); - - final AttributeDefinitionDraft setOfCustomerAttributeDef = - AttributeDefinitionDraftBuilder.of( - SetAttributeType.of(ReferenceAttributeType.of(Customer.referenceTypeId())), - "customers", - ofEnglish("customers"), - false) - .searchable(false) - .attributeConstraint(AttributeConstraint.NONE) - .build(); - - final ProductTypeDraft nestedProductTypeDraft = - ProductTypeDraftBuilder.of( - INNER_PRODUCT_TYPE_KEY, - INNER_PRODUCT_TYPE_KEY, - "an inner productType for t-shirts", - emptyList()) - .attributes( - asList( - setOfCategoriesAttributeDef, - setOfProductTypeAttributeDef, - setOfCustomObjectAttributeDef, - setOfStateAttributeDef, - setOfCustomerAttributeDef)) - .build(); - - final ProductType innerProductType = - sourceProjectClient - .execute(ProductTypeCreateCommand.of(nestedProductTypeDraft)) - .toCompletableFuture() - .join(); - - final AttributeDefinitionDraft nestedAttribute = - AttributeDefinitionDraftBuilder.of( - SetAttributeType.of(NestedAttributeType.of(innerProductType)), - NESTED_ATTRIBUTE_NAME, - ofEnglish("nested attribute"), - false) - .searchable(false) - .attributeConstraint(AttributeConstraint.NONE) - .build(); - - final ProductTypeDraft productTypeDraft = - ProductTypeDraftBuilder.of( - MAIN_PRODUCT_TYPE_KEY, - MAIN_PRODUCT_TYPE_KEY, - "a productType for t-shirts", - emptyList()) - .attributes(singletonList(nestedAttribute)) - .build(); - - final ProductType mainProductType = - sourceProjectClient - .execute(ProductTypeCreateCommand.of(productTypeDraft)) - .toCompletableFuture() - .join(); - - final CategoryDraft categoryDraft = - CategoryDraftBuilder.of(ofEnglish("t-shirts"), ofEnglish("t-shirts")) - .key(CATEGORY_KEY) - .build(); - - final Category category = - sourceProjectClient - .execute(CategoryCreateCommand.of(categoryDraft)) - .toCompletableFuture() - .join(); - - final StateDraft stateDraft = - StateDraftBuilder.of(STATE_KEY, StateType.PRODUCT_STATE) - .roles(Collections.emptySet()) - .description(ofEnglish("states")) - .name(ofEnglish("states")) - .initial(true) - .transitions(Collections.emptySet()) - .build(); - - final State state = - sourceProjectClient.execute(StateCreateCommand.of(stateDraft)).toCompletableFuture().join(); - - final CustomerDraft customerDraft = - CustomerDraftBuilder.of("test@email.com", "testPassword").key(CUSTOMER_KEY).build(); - - final CustomerSignInResult customerSignInResult = - sourceProjectClient - .execute(CustomerCreateCommand.of(customerDraft)) - .toCompletableFuture() - .join(); - final Customer customer = customerSignInResult.getCustomer(); - - final ObjectNode customObjectValue = - JsonNodeFactory.instance.objectNode().put("field", "value1"); - - final CustomObjectDraft customObjectDraft = - CustomObjectDraft.ofUnversionedUpsert("container", "key1", customObjectValue); - - final ObjectNode customObjectValue2 = - JsonNodeFactory.instance.objectNode().put("field", "value2"); - - final CustomObjectDraft customObjectDraft2 = - CustomObjectDraft.ofUnversionedUpsert("container", "key2", customObjectValue2); - - final CustomObject customObject1 = - sourceProjectClient - .execute(CustomObjectUpsertCommand.of(customObjectDraft)) - .toCompletableFuture() - .join(); - - final CustomObject customObject2 = - sourceProjectClient - .execute(CustomObjectUpsertCommand.of(customObjectDraft2)) - .toCompletableFuture() - .join(); - - final ArrayNode setAttributeValue = JsonNodeFactory.instance.arrayNode(); - - final ArrayNode nestedAttributeValue = JsonNodeFactory.instance.arrayNode(); - - final ArrayNode categoriesReferencesAttributeValue = JsonNodeFactory.instance.arrayNode(); - categoriesReferencesAttributeValue.add( - createReferenceObject(Category.referenceTypeId(), category.getId())); - - final ArrayNode productTypesReferencesAttributeValue = JsonNodeFactory.instance.arrayNode(); - productTypesReferencesAttributeValue.add( - createReferenceObject(ProductType.referenceTypeId(), mainProductType.getId())); - - final ArrayNode customObjectReferencesAttributeValue = JsonNodeFactory.instance.arrayNode(); - customObjectReferencesAttributeValue.add( - createReferenceObject(CustomObject.referenceTypeId(), customObject1.getId())); - customObjectReferencesAttributeValue.add( - createReferenceObject(CustomObject.referenceTypeId(), customObject2.getId())); - - final ArrayNode stateReferenceAttributeValue = JsonNodeFactory.instance.arrayNode(); - stateReferenceAttributeValue.add(createReferenceObject(State.referenceTypeId(), state.getId())); - - final ArrayNode customerReferenceAttributeValue = JsonNodeFactory.instance.arrayNode(); - customerReferenceAttributeValue.add( - createReferenceObject(Customer.referenceTypeId(), customer.getId())); - - nestedAttributeValue.add( - createAttributeObject( - setOfCategoriesAttributeDef.getName(), categoriesReferencesAttributeValue)); - nestedAttributeValue.add( - createAttributeObject( - setOfProductTypeAttributeDef.getName(), productTypesReferencesAttributeValue)); - nestedAttributeValue.add( - createAttributeObject( - setOfCustomObjectAttributeDef.getName(), customObjectReferencesAttributeValue)); - nestedAttributeValue.add( - createAttributeObject(setOfStateAttributeDef.getName(), stateReferenceAttributeValue)); - nestedAttributeValue.add( - createAttributeObject( - setOfCustomerAttributeDef.getName(), customerReferenceAttributeValue)); - - setAttributeValue.add(nestedAttributeValue); - - final AttributeDraft setOfNestedAttribute = - AttributeDraft.of(nestedAttribute.getName(), setAttributeValue); - - final ProductVariantDraft masterVariant = - ProductVariantDraftBuilder.of() - .key(MAIN_PRODUCT_MASTER_VARIANT_KEY) - .sku(MAIN_PRODUCT_MASTER_VARIANT_KEY) - .attributes(setOfNestedAttribute) - .build(); - - final ProductDraft productDraftWithNestedAttribute = - ProductDraftBuilder.of( - mainProductType, - ofEnglish(MAIN_PRODUCT_KEY), - ofEnglish(MAIN_PRODUCT_KEY), - masterVariant) - .key(MAIN_PRODUCT_KEY) - .build(); - - sourceProjectClient - .execute(ProductCreateCommand.of(productDraftWithNestedAttribute)) - .toCompletableFuture() - .join(); - } - - @AfterAll - static void tearDownSuite() { - cleanUpProjects(CTP_SOURCE_CLIENT, CTP_TARGET_CLIENT); - } - - @Test - void run_WithSyncAsArgumentWithAllArgAsFullSync_ShouldExecuteAllSyncers() { - // test - CliRunner.of() - .run(new String[] {"-s", "all", "-r", "runnerName", "-f"}, createITSyncerFactory()); - - assertThat(cliRunnerTestLogger.getAllLoggingEvents()) - .allMatch(loggingEvent -> !Level.ERROR.equals(loggingEvent.getLevel())); - - assertTypeSyncerLoggingEvents(typeSyncerTestLogger, 0); - assertProductTypeSyncerLoggingEvents(productTypeSyncerTestLogger, 2); - assertTaxCategorySyncerLoggingEvents(taxCategorySyncerTestLogger, 0); - assertCategorySyncerLoggingEvents(categorySyncerTestLogger, 1); - assertProductSyncerLoggingEvents(productSyncerTestLogger, 1); - assertInventoryEntrySyncerLoggingEvents(inventoryEntrySyncerTestLogger, 0); - assertCartDiscountSyncerLoggingEvents(cartDiscountSyncerTestLogger, 0); - assertStateSyncerLoggingEvents(stateSyncerTestLogger, 2); - assertCustomObjectSyncerLoggingEvents(customObjectSyncerTestLogger, 2); - assertCustomerSyncerLoggingEvents(customerSyncerTestLogger, 1); - assertShoppingListSyncerLoggingEvents(shoppingListSyncerTestLogger, 0); - - assertAllResourcesAreSyncedToTarget(CTP_TARGET_CLIENT); - } - - private static void assertAllResourcesAreSyncedToTarget( - @Nonnull final SphereClient targetClient) { - - assertProductTypeExists(targetClient, INNER_PRODUCT_TYPE_KEY); - final ProductType productType = assertProductTypeExists(targetClient, MAIN_PRODUCT_TYPE_KEY); - final Category category = assertCategoryExists(targetClient, CATEGORY_KEY); - final State state = assertStateExists(targetClient, STATE_KEY); - final Customer customer = assertCustomerExists(targetClient, CUSTOMER_KEY); - - final PagedQueryResult productQueryResult = - targetClient.execute(ProductQuery.of()).toCompletableFuture().join(); - - assertThat(productQueryResult.getResults()) - .hasSize(1) - .singleElement() - .satisfies( - product -> { - assertThat(product.getKey()).isEqualTo(MAIN_PRODUCT_KEY); - final ProductVariant stagedMasterVariant = - product.getMasterData().getStaged().getMasterVariant(); - assertThat(stagedMasterVariant.getKey()).isEqualTo(MAIN_PRODUCT_MASTER_VARIANT_KEY); - assertThat(stagedMasterVariant.getAttributes()).hasSize(1); - assertThat(stagedMasterVariant.getAttribute(NESTED_ATTRIBUTE_NAME)) - .satisfies( - attribute -> { - final JsonNode attributeValue = attribute.getValueAsJsonNode(); - assertThat(attributeValue).isExactlyInstanceOf(ArrayNode.class); - final ArrayNode attributeValueAsArray = (ArrayNode) attributeValue; - assertThat(attributeValueAsArray).hasSize(1); - - final JsonNode nestedAttributeElement = attributeValueAsArray.get(0); - assertThat(nestedAttributeElement).isExactlyInstanceOf(ArrayNode.class); - final ArrayNode nestedTypeAttributes = (ArrayNode) nestedAttributeElement; - assertThat(nestedTypeAttributes).hasSize(5); - - assertThat(nestedTypeAttributes.get(0).get("name").asText()) - .isEqualTo("categories"); - assertThat(nestedTypeAttributes.get(0).get("value")) - .isExactlyInstanceOf(ArrayNode.class); - final ArrayNode categoryReferences = - (ArrayNode) (nestedTypeAttributes.get(0).get("value")); - assertThat(categoryReferences) - .singleElement() - .satisfies( - categoryReference -> - assertThat(categoryReference.get("id").asText()) - .isEqualTo(category.getId())); - - assertThat(nestedTypeAttributes.get(1).get("name").asText()) - .isEqualTo("productTypes"); - assertThat(nestedTypeAttributes.get(1).get("value")) - .isExactlyInstanceOf(ArrayNode.class); - final ArrayNode productTypeReferences = - (ArrayNode) (nestedTypeAttributes.get(1).get("value")); - assertThat(productTypeReferences) - .singleElement() - .satisfies( - productTypeReference -> - assertThat(productTypeReference.get("id").asText()) - .isEqualTo(productType.getId())); - - assertThat(nestedTypeAttributes.get(2).get("name").asText()) - .isEqualTo("customObjects"); - assertThat(nestedTypeAttributes.get(2).get("value")) - .isExactlyInstanceOf(ArrayNode.class); - final ArrayNode customObjectReferences = - (ArrayNode) (nestedTypeAttributes.get(2).get("value")); - assertThat(customObjectReferences).hasSize(2); - - assertThat(nestedTypeAttributes.get(3).get("name").asText()) - .isEqualTo("states"); - assertThat(nestedTypeAttributes.get(3).get("value")) - .isExactlyInstanceOf(ArrayNode.class); - final ArrayNode stateReferences = - (ArrayNode) (nestedTypeAttributes.get(3).get("value")); - assertThat(stateReferences) - .singleElement() - .satisfies( - stateReference -> - assertThat(stateReference.get("id").asText()) - .isEqualTo(state.getId())); - - assertThat(nestedTypeAttributes.get(4).get("name").asText()) - .isEqualTo("customers"); - assertThat(nestedTypeAttributes.get(4).get("value")) - .isExactlyInstanceOf(ArrayNode.class); - final ArrayNode customerReferences = - (ArrayNode) (nestedTypeAttributes.get(4).get("value")); - assertThat(customerReferences) - .singleElement() - .satisfies( - customerReference -> - assertThat(customerReference.get("id").asText()) - .isEqualTo(customer.getId())); - }); - }); - } -} +// package com.commercetools.project.sync; +// +// import static com.commercetools.project.sync.util.CtpClientUtils.CTP_SOURCE_CLIENT; +// import static com.commercetools.project.sync.util.CtpClientUtils.CTP_TARGET_CLIENT; +// import static com.commercetools.project.sync.util.IntegrationTestUtils.assertCategoryExists; +// import static com.commercetools.project.sync.util.IntegrationTestUtils.assertCustomerExists; +// import static com.commercetools.project.sync.util.IntegrationTestUtils.assertProductTypeExists; +// import static com.commercetools.project.sync.util.IntegrationTestUtils.assertStateExists; +// import static com.commercetools.project.sync.util.IntegrationTestUtils.cleanUpProjects; +// import static com.commercetools.project.sync.util.IntegrationTestUtils.createAttributeObject; +// import static com.commercetools.project.sync.util.IntegrationTestUtils.createITSyncerFactory; +// import static com.commercetools.project.sync.util.IntegrationTestUtils.createReferenceObject; +// import static +// com.commercetools.project.sync.util.TestUtils.assertCartDiscountSyncerLoggingEvents; +// import static com.commercetools.project.sync.util.TestUtils.assertCategorySyncerLoggingEvents; +// import static +// com.commercetools.project.sync.util.TestUtils.assertCustomObjectSyncerLoggingEvents; +// import static com.commercetools.project.sync.util.TestUtils.assertCustomerSyncerLoggingEvents; +// import static +// com.commercetools.project.sync.util.TestUtils.assertInventoryEntrySyncerLoggingEvents; +// import static com.commercetools.project.sync.util.TestUtils.assertProductSyncerLoggingEvents; +// import static com.commercetools.project.sync.util.TestUtils.assertProductTypeSyncerLoggingEvents; +// import static +// com.commercetools.project.sync.util.TestUtils.assertShoppingListSyncerLoggingEvents; +// import static com.commercetools.project.sync.util.TestUtils.assertStateSyncerLoggingEvents; +// import static com.commercetools.project.sync.util.TestUtils.assertTaxCategorySyncerLoggingEvents; +// import static com.commercetools.project.sync.util.TestUtils.assertTypeSyncerLoggingEvents; +// import static io.sphere.sdk.models.LocalizedString.ofEnglish; +// import static java.util.Arrays.asList; +// import static java.util.Collections.emptyList; +// import static java.util.Collections.singletonList; +// import static org.assertj.core.api.Assertions.assertThat; +// +// import com.commercetools.project.sync.cartdiscount.CartDiscountSyncer; +// import com.commercetools.project.sync.category.CategorySyncer; +// import com.commercetools.project.sync.customer.CustomerSyncer; +// import com.commercetools.project.sync.customobject.CustomObjectSyncer; +// import com.commercetools.project.sync.inventoryentry.InventoryEntrySyncer; +// import com.commercetools.project.sync.product.ProductSyncer; +// import com.commercetools.project.sync.producttype.ProductTypeSyncer; +// import com.commercetools.project.sync.shoppinglist.ShoppingListSyncer; +// import com.commercetools.project.sync.state.StateSyncer; +// import com.commercetools.project.sync.taxcategory.TaxCategorySyncer; +// import com.commercetools.project.sync.type.TypeSyncer; +// import com.fasterxml.jackson.databind.JsonNode; +// import com.fasterxml.jackson.databind.node.ArrayNode; +// import com.fasterxml.jackson.databind.node.JsonNodeFactory; +// import com.fasterxml.jackson.databind.node.ObjectNode; +// import io.sphere.sdk.categories.Category; +// import io.sphere.sdk.categories.CategoryDraft; +// import io.sphere.sdk.categories.CategoryDraftBuilder; +// import io.sphere.sdk.categories.commands.CategoryCreateCommand; +// import io.sphere.sdk.client.SphereClient; +// import io.sphere.sdk.customers.Customer; +// import io.sphere.sdk.customers.CustomerDraft; +// import io.sphere.sdk.customers.CustomerDraftBuilder; +// import io.sphere.sdk.customers.CustomerSignInResult; +// import io.sphere.sdk.customers.commands.CustomerCreateCommand; +// import io.sphere.sdk.customobjects.CustomObject; +// import io.sphere.sdk.customobjects.CustomObjectDraft; +// import io.sphere.sdk.customobjects.commands.CustomObjectUpsertCommand; +// import io.sphere.sdk.products.Product; +// import io.sphere.sdk.products.ProductDraft; +// import io.sphere.sdk.products.ProductDraftBuilder; +// import io.sphere.sdk.products.ProductVariant; +// import io.sphere.sdk.products.ProductVariantDraft; +// import io.sphere.sdk.products.ProductVariantDraftBuilder; +// import io.sphere.sdk.products.attributes.AttributeConstraint; +// import io.sphere.sdk.products.attributes.AttributeDefinitionDraft; +// import io.sphere.sdk.products.attributes.AttributeDefinitionDraftBuilder; +// import io.sphere.sdk.products.attributes.AttributeDraft; +// import io.sphere.sdk.products.attributes.NestedAttributeType; +// import io.sphere.sdk.products.attributes.ReferenceAttributeType; +// import io.sphere.sdk.products.attributes.SetAttributeType; +// import io.sphere.sdk.products.commands.ProductCreateCommand; +// import io.sphere.sdk.products.queries.ProductQuery; +// import io.sphere.sdk.producttypes.ProductType; +// import io.sphere.sdk.producttypes.ProductTypeDraft; +// import io.sphere.sdk.producttypes.ProductTypeDraftBuilder; +// import io.sphere.sdk.producttypes.commands.ProductTypeCreateCommand; +// import io.sphere.sdk.queries.PagedQueryResult; +// import io.sphere.sdk.states.State; +// import io.sphere.sdk.states.StateDraft; +// import io.sphere.sdk.states.StateDraftBuilder; +// import io.sphere.sdk.states.StateType; +// import io.sphere.sdk.states.commands.StateCreateCommand; +// import java.util.Collections; +// import javax.annotation.Nonnull; +// import org.junit.jupiter.api.AfterAll; +// import org.junit.jupiter.api.BeforeEach; +// import org.junit.jupiter.api.Test; +// import uk.org.lidalia.slf4jext.Level; +// import uk.org.lidalia.slf4jtest.TestLogger; +// import uk.org.lidalia.slf4jtest.TestLoggerFactory; +// +//// This will suppress MoreThanOneLogger warnings in this class +// @SuppressWarnings("PMD.MoreThanOneLogger") +// class ProductSyncWithNestedReferencesIT { +// +// private static final TestLogger cliRunnerTestLogger = +// TestLoggerFactory.getTestLogger(CliRunner.class); +// private static final TestLogger productSyncerTestLogger = +// TestLoggerFactory.getTestLogger(ProductSyncer.class); +// private static final TestLogger productTypeSyncerTestLogger = +// TestLoggerFactory.getTestLogger(ProductTypeSyncer.class); +// private static final TestLogger customerSyncerTestLogger = +// TestLoggerFactory.getTestLogger(CustomerSyncer.class); +// private static final TestLogger shoppingListSyncerTestLogger = +// TestLoggerFactory.getTestLogger(ShoppingListSyncer.class); +// private static final TestLogger stateSyncerTestLogger = +// TestLoggerFactory.getTestLogger(StateSyncer.class); +// private static final TestLogger inventoryEntrySyncerTestLogger = +// TestLoggerFactory.getTestLogger(InventoryEntrySyncer.class); +// private static final TestLogger customObjectSyncerTestLogger = +// TestLoggerFactory.getTestLogger(CustomObjectSyncer.class); +// private static final TestLogger typeSyncerTestLogger = +// TestLoggerFactory.getTestLogger(TypeSyncer.class); +// private static final TestLogger categorySyncerTestLogger = +// TestLoggerFactory.getTestLogger(CategorySyncer.class); +// private static final TestLogger cartDiscountSyncerTestLogger = +// TestLoggerFactory.getTestLogger(CartDiscountSyncer.class); +// private static final TestLogger taxCategorySyncerTestLogger = +// TestLoggerFactory.getTestLogger(TaxCategorySyncer.class); +// +// private static final String INNER_PRODUCT_TYPE_KEY = "inner-product-type"; +// private static final String MAIN_PRODUCT_TYPE_KEY = "sample-product-type"; +// private static final String CATEGORY_KEY = "category-key"; +// private static final String MAIN_PRODUCT_MASTER_VARIANT_KEY = "main-product-master-variant-key"; +// private static final String MAIN_PRODUCT_KEY = "product-with-nested"; +// private static final String NESTED_ATTRIBUTE_NAME = "nested-attribute"; +// private static final String STATE_KEY = "state-key"; +// private static final String CUSTOMER_KEY = "customer-key"; +// +// @BeforeEach +// void setup() { +// cliRunnerTestLogger.clearAll(); +// productSyncerTestLogger.clearAll(); +// productTypeSyncerTestLogger.clearAll(); +// customerSyncerTestLogger.clearAll(); +// shoppingListSyncerTestLogger.clearAll(); +// stateSyncerTestLogger.clearAll(); +// inventoryEntrySyncerTestLogger.clearAll(); +// customObjectSyncerTestLogger.clearAll(); +// typeSyncerTestLogger.clearAll(); +// categorySyncerTestLogger.clearAll(); +// cartDiscountSyncerTestLogger.clearAll(); +// taxCategorySyncerTestLogger.clearAll(); +// cleanUpProjects(CTP_SOURCE_CLIENT, CTP_TARGET_CLIENT); +// setupSourceProjectData(CTP_SOURCE_CLIENT); +// } +// +// static void setupSourceProjectData(@Nonnull final SphereClient sourceProjectClient) { +// final AttributeDefinitionDraft setOfCategoriesAttributeDef = +// AttributeDefinitionDraftBuilder.of( +// SetAttributeType.of(ReferenceAttributeType.ofCategory()), +// "categories", +// ofEnglish("categories"), +// false) +// .searchable(false) +// .attributeConstraint(AttributeConstraint.NONE) +// .build(); +// +// final AttributeDefinitionDraft setOfProductTypeAttributeDef = +// AttributeDefinitionDraftBuilder.of( +// SetAttributeType.of(ReferenceAttributeType.ofProductType()), +// "productTypes", +// ofEnglish("productTypes"), +// false) +// .searchable(false) +// .attributeConstraint(AttributeConstraint.NONE) +// .build(); +// +// final AttributeDefinitionDraft setOfCustomObjectAttributeDef = +// AttributeDefinitionDraftBuilder.of( +// SetAttributeType.of(ReferenceAttributeType.of(CustomObject.referenceTypeId())), +// "customObjects", +// ofEnglish("customObjects"), +// false) +// .searchable(false) +// .attributeConstraint(AttributeConstraint.NONE) +// .build(); +// +// final AttributeDefinitionDraft setOfStateAttributeDef = +// AttributeDefinitionDraftBuilder.of( +// SetAttributeType.of(ReferenceAttributeType.of(State.referenceTypeId())), +// "states", +// ofEnglish("states"), +// false) +// .searchable(false) +// .attributeConstraint(AttributeConstraint.NONE) +// .build(); +// +// final AttributeDefinitionDraft setOfCustomerAttributeDef = +// AttributeDefinitionDraftBuilder.of( +// SetAttributeType.of(ReferenceAttributeType.of(Customer.referenceTypeId())), +// "customers", +// ofEnglish("customers"), +// false) +// .searchable(false) +// .attributeConstraint(AttributeConstraint.NONE) +// .build(); +// +// final ProductTypeDraft nestedProductTypeDraft = +// ProductTypeDraftBuilder.of( +// INNER_PRODUCT_TYPE_KEY, +// INNER_PRODUCT_TYPE_KEY, +// "an inner productType for t-shirts", +// emptyList()) +// .attributes( +// asList( +// setOfCategoriesAttributeDef, +// setOfProductTypeAttributeDef, +// setOfCustomObjectAttributeDef, +// setOfStateAttributeDef, +// setOfCustomerAttributeDef)) +// .build(); +// +// final ProductType innerProductType = +// sourceProjectClient +// .execute(ProductTypeCreateCommand.of(nestedProductTypeDraft)) +// .toCompletableFuture() +// .join(); +// +// final AttributeDefinitionDraft nestedAttribute = +// AttributeDefinitionDraftBuilder.of( +// SetAttributeType.of(NestedAttributeType.of(innerProductType)), +// NESTED_ATTRIBUTE_NAME, +// ofEnglish("nested attribute"), +// false) +// .searchable(false) +// .attributeConstraint(AttributeConstraint.NONE) +// .build(); +// +// final ProductTypeDraft productTypeDraft = +// ProductTypeDraftBuilder.of( +// MAIN_PRODUCT_TYPE_KEY, +// MAIN_PRODUCT_TYPE_KEY, +// "a productType for t-shirts", +// emptyList()) +// .attributes(singletonList(nestedAttribute)) +// .build(); +// +// final ProductType mainProductType = +// sourceProjectClient +// .execute(ProductTypeCreateCommand.of(productTypeDraft)) +// .toCompletableFuture() +// .join(); +// +// final CategoryDraft categoryDraft = +// CategoryDraftBuilder.of(ofEnglish("t-shirts"), ofEnglish("t-shirts")) +// .key(CATEGORY_KEY) +// .build(); +// +// final Category category = +// sourceProjectClient +// .execute(CategoryCreateCommand.of(categoryDraft)) +// .toCompletableFuture() +// .join(); +// +// final StateDraft stateDraft = +// StateDraftBuilder.of(STATE_KEY, StateType.PRODUCT_STATE) +// .roles(Collections.emptySet()) +// .description(ofEnglish("states")) +// .name(ofEnglish("states")) +// .initial(true) +// .transitions(Collections.emptySet()) +// .build(); +// +// final State state = +// +// sourceProjectClient.execute(StateCreateCommand.of(stateDraft)).toCompletableFuture().join(); +// +// final CustomerDraft customerDraft = +// CustomerDraftBuilder.of("test@email.com", "testPassword").key(CUSTOMER_KEY).build(); +// +// final CustomerSignInResult customerSignInResult = +// sourceProjectClient +// .execute(CustomerCreateCommand.of(customerDraft)) +// .toCompletableFuture() +// .join(); +// final Customer customer = customerSignInResult.getCustomer(); +// +// final ObjectNode customObjectValue = +// JsonNodeFactory.instance.objectNode().put("field", "value1"); +// +// final CustomObjectDraft customObjectDraft = +// CustomObjectDraft.ofUnversionedUpsert("container", "key1", customObjectValue); +// +// final ObjectNode customObjectValue2 = +// JsonNodeFactory.instance.objectNode().put("field", "value2"); +// +// final CustomObjectDraft customObjectDraft2 = +// CustomObjectDraft.ofUnversionedUpsert("container", "key2", customObjectValue2); +// +// final CustomObject customObject1 = +// sourceProjectClient +// .execute(CustomObjectUpsertCommand.of(customObjectDraft)) +// .toCompletableFuture() +// .join(); +// +// final CustomObject customObject2 = +// sourceProjectClient +// .execute(CustomObjectUpsertCommand.of(customObjectDraft2)) +// .toCompletableFuture() +// .join(); +// +// final ArrayNode setAttributeValue = JsonNodeFactory.instance.arrayNode(); +// +// final ArrayNode nestedAttributeValue = JsonNodeFactory.instance.arrayNode(); +// +// final ArrayNode categoriesReferencesAttributeValue = JsonNodeFactory.instance.arrayNode(); +// categoriesReferencesAttributeValue.add( +// createReferenceObject(Category.referenceTypeId(), category.getId())); +// +// final ArrayNode productTypesReferencesAttributeValue = JsonNodeFactory.instance.arrayNode(); +// productTypesReferencesAttributeValue.add( +// createReferenceObject(ProductType.referenceTypeId(), mainProductType.getId())); +// +// final ArrayNode customObjectReferencesAttributeValue = JsonNodeFactory.instance.arrayNode(); +// customObjectReferencesAttributeValue.add( +// createReferenceObject(CustomObject.referenceTypeId(), customObject1.getId())); +// customObjectReferencesAttributeValue.add( +// createReferenceObject(CustomObject.referenceTypeId(), customObject2.getId())); +// +// final ArrayNode stateReferenceAttributeValue = JsonNodeFactory.instance.arrayNode(); +// stateReferenceAttributeValue.add(createReferenceObject(State.referenceTypeId(), +// state.getId())); +// +// final ArrayNode customerReferenceAttributeValue = JsonNodeFactory.instance.arrayNode(); +// customerReferenceAttributeValue.add( +// createReferenceObject(Customer.referenceTypeId(), customer.getId())); +// +// nestedAttributeValue.add( +// createAttributeObject( +// setOfCategoriesAttributeDef.getName(), categoriesReferencesAttributeValue)); +// nestedAttributeValue.add( +// createAttributeObject( +// setOfProductTypeAttributeDef.getName(), productTypesReferencesAttributeValue)); +// nestedAttributeValue.add( +// createAttributeObject( +// setOfCustomObjectAttributeDef.getName(), customObjectReferencesAttributeValue)); +// nestedAttributeValue.add( +// createAttributeObject(setOfStateAttributeDef.getName(), stateReferenceAttributeValue)); +// nestedAttributeValue.add( +// createAttributeObject( +// setOfCustomerAttributeDef.getName(), customerReferenceAttributeValue)); +// +// setAttributeValue.add(nestedAttributeValue); +// +// final AttributeDraft setOfNestedAttribute = +// AttributeDraft.of(nestedAttribute.getName(), setAttributeValue); +// +// final ProductVariantDraft masterVariant = +// ProductVariantDraftBuilder.of() +// .key(MAIN_PRODUCT_MASTER_VARIANT_KEY) +// .sku(MAIN_PRODUCT_MASTER_VARIANT_KEY) +// .attributes(setOfNestedAttribute) +// .build(); +// +// final ProductDraft productDraftWithNestedAttribute = +// ProductDraftBuilder.of( +// mainProductType, +// ofEnglish(MAIN_PRODUCT_KEY), +// ofEnglish(MAIN_PRODUCT_KEY), +// masterVariant) +// .key(MAIN_PRODUCT_KEY) +// .build(); +// +// sourceProjectClient +// .execute(ProductCreateCommand.of(productDraftWithNestedAttribute)) +// .toCompletableFuture() +// .join(); +// } +// +// @AfterAll +// static void tearDownSuite() { +// cleanUpProjects(CTP_SOURCE_CLIENT, CTP_TARGET_CLIENT); +// } +// +// @Test +// void run_WithSyncAsArgumentWithAllArgAsFullSync_ShouldExecuteAllSyncers() { +// // test +// CliRunner.of() +// .run(new String[] {"-s", "all", "-r", "runnerName", "-f"}, createITSyncerFactory()); +// +// assertThat(cliRunnerTestLogger.getAllLoggingEvents()) +// .allMatch(loggingEvent -> !Level.ERROR.equals(loggingEvent.getLevel())); +// +// assertTypeSyncerLoggingEvents(typeSyncerTestLogger, 0); +// assertProductTypeSyncerLoggingEvents(productTypeSyncerTestLogger, 2); +// assertTaxCategorySyncerLoggingEvents(taxCategorySyncerTestLogger, 0); +// assertCategorySyncerLoggingEvents(categorySyncerTestLogger, 1); +// assertProductSyncerLoggingEvents(productSyncerTestLogger, 1); +// assertInventoryEntrySyncerLoggingEvents(inventoryEntrySyncerTestLogger, 0); +// assertCartDiscountSyncerLoggingEvents(cartDiscountSyncerTestLogger, 0); +// assertStateSyncerLoggingEvents(stateSyncerTestLogger, 2); +// assertCustomObjectSyncerLoggingEvents(customObjectSyncerTestLogger, 2); +// assertCustomerSyncerLoggingEvents(customerSyncerTestLogger, 1); +// assertShoppingListSyncerLoggingEvents(shoppingListSyncerTestLogger, 0); +// +// assertAllResourcesAreSyncedToTarget(CTP_TARGET_CLIENT); +// } +// +// private static void assertAllResourcesAreSyncedToTarget( +// @Nonnull final SphereClient targetClient) { +// +// assertProductTypeExists(targetClient, INNER_PRODUCT_TYPE_KEY); +// final ProductType productType = assertProductTypeExists(targetClient, MAIN_PRODUCT_TYPE_KEY); +// final Category category = assertCategoryExists(targetClient, CATEGORY_KEY); +// final State state = assertStateExists(targetClient, STATE_KEY); +// final Customer customer = assertCustomerExists(targetClient, CUSTOMER_KEY); +// +// final PagedQueryResult productQueryResult = +// targetClient.execute(ProductQuery.of()).toCompletableFuture().join(); +// +// assertThat(productQueryResult.getResults()) +// .hasSize(1) +// .singleElement() +// .satisfies( +// product -> { +// assertThat(product.getKey()).isEqualTo(MAIN_PRODUCT_KEY); +// final ProductVariant stagedMasterVariant = +// product.getMasterData().getStaged().getMasterVariant(); +// assertThat(stagedMasterVariant.getKey()).isEqualTo(MAIN_PRODUCT_MASTER_VARIANT_KEY); +// assertThat(stagedMasterVariant.getAttributes()).hasSize(1); +// assertThat(stagedMasterVariant.getAttribute(NESTED_ATTRIBUTE_NAME)) +// .satisfies( +// attribute -> { +// final JsonNode attributeValue = attribute.getValueAsJsonNode(); +// assertThat(attributeValue).isExactlyInstanceOf(ArrayNode.class); +// final ArrayNode attributeValueAsArray = (ArrayNode) attributeValue; +// assertThat(attributeValueAsArray).hasSize(1); +// +// final JsonNode nestedAttributeElement = attributeValueAsArray.get(0); +// assertThat(nestedAttributeElement).isExactlyInstanceOf(ArrayNode.class); +// final ArrayNode nestedTypeAttributes = (ArrayNode) nestedAttributeElement; +// assertThat(nestedTypeAttributes).hasSize(5); +// +// assertThat(nestedTypeAttributes.get(0).get("name").asText()) +// .isEqualTo("categories"); +// assertThat(nestedTypeAttributes.get(0).get("value")) +// .isExactlyInstanceOf(ArrayNode.class); +// final ArrayNode categoryReferences = +// (ArrayNode) (nestedTypeAttributes.get(0).get("value")); +// assertThat(categoryReferences) +// .singleElement() +// .satisfies( +// categoryReference -> +// assertThat(categoryReference.get("id").asText()) +// .isEqualTo(category.getId())); +// +// assertThat(nestedTypeAttributes.get(1).get("name").asText()) +// .isEqualTo("productTypes"); +// assertThat(nestedTypeAttributes.get(1).get("value")) +// .isExactlyInstanceOf(ArrayNode.class); +// final ArrayNode productTypeReferences = +// (ArrayNode) (nestedTypeAttributes.get(1).get("value")); +// assertThat(productTypeReferences) +// .singleElement() +// .satisfies( +// productTypeReference -> +// assertThat(productTypeReference.get("id").asText()) +// .isEqualTo(productType.getId())); +// +// assertThat(nestedTypeAttributes.get(2).get("name").asText()) +// .isEqualTo("customObjects"); +// assertThat(nestedTypeAttributes.get(2).get("value")) +// .isExactlyInstanceOf(ArrayNode.class); +// final ArrayNode customObjectReferences = +// (ArrayNode) (nestedTypeAttributes.get(2).get("value")); +// assertThat(customObjectReferences).hasSize(2); +// +// assertThat(nestedTypeAttributes.get(3).get("name").asText()) +// .isEqualTo("states"); +// assertThat(nestedTypeAttributes.get(3).get("value")) +// .isExactlyInstanceOf(ArrayNode.class); +// final ArrayNode stateReferences = +// (ArrayNode) (nestedTypeAttributes.get(3).get("value")); +// assertThat(stateReferences) +// .singleElement() +// .satisfies( +// stateReference -> +// assertThat(stateReference.get("id").asText()) +// .isEqualTo(state.getId())); +// +// assertThat(nestedTypeAttributes.get(4).get("name").asText()) +// .isEqualTo("customers"); +// assertThat(nestedTypeAttributes.get(4).get("value")) +// .isExactlyInstanceOf(ArrayNode.class); +// final ArrayNode customerReferences = +// (ArrayNode) (nestedTypeAttributes.get(4).get("value")); +// assertThat(customerReferences) +// .singleElement() +// .satisfies( +// customerReference -> +// assertThat(customerReference.get("id").asText()) +// .isEqualTo(customer.getId())); +// }); +// }); +// } +// } diff --git a/src/integration-test/java/com/commercetools/project/sync/ProductSyncWithReferenceResolutionIT.java b/src/integration-test/java/com/commercetools/project/sync/ProductSyncWithReferenceResolutionIT.java index cf03f1ac..2efa6db7 100644 --- a/src/integration-test/java/com/commercetools/project/sync/ProductSyncWithReferenceResolutionIT.java +++ b/src/integration-test/java/com/commercetools/project/sync/ProductSyncWithReferenceResolutionIT.java @@ -1,307 +1,310 @@ -package com.commercetools.project.sync; - -import static com.commercetools.project.sync.util.CtpClientUtils.CTP_SOURCE_CLIENT; -import static com.commercetools.project.sync.util.CtpClientUtils.CTP_TARGET_CLIENT; -import static com.commercetools.project.sync.util.IntegrationTestUtils.assertCategoryExists; -import static com.commercetools.project.sync.util.IntegrationTestUtils.assertProductExists; -import static com.commercetools.project.sync.util.IntegrationTestUtils.assertProductTypeExists; -import static com.commercetools.project.sync.util.IntegrationTestUtils.cleanUpProjects; -import static com.commercetools.project.sync.util.IntegrationTestUtils.createITSyncerFactory; -import static com.neovisionaries.i18n.CountryCode.DE; -import static io.sphere.sdk.models.DefaultCurrencyUnits.EUR; -import static io.sphere.sdk.models.LocalizedString.ofEnglish; -import static java.lang.String.format; -import static java.util.Arrays.asList; -import static java.util.Collections.emptyList; -import static java.util.Collections.emptyMap; -import static java.util.Collections.singleton; -import static java.util.Collections.singletonList; -import static java.util.Optional.ofNullable; -import static org.assertj.core.api.Assertions.assertThat; - -import com.commercetools.project.sync.product.ProductSyncer; -import com.neovisionaries.i18n.CountryCode; -import io.sphere.sdk.categories.CategoryDraft; -import io.sphere.sdk.categories.CategoryDraftBuilder; -import io.sphere.sdk.categories.commands.CategoryCreateCommand; -import io.sphere.sdk.channels.Channel; -import io.sphere.sdk.channels.ChannelDraft; -import io.sphere.sdk.channels.ChannelDraftBuilder; -import io.sphere.sdk.channels.ChannelRole; -import io.sphere.sdk.channels.commands.ChannelCreateCommand; -import io.sphere.sdk.client.SphereClient; -import io.sphere.sdk.customergroups.CustomerGroup; -import io.sphere.sdk.customergroups.CustomerGroupDraft; -import io.sphere.sdk.customergroups.CustomerGroupDraftBuilder; -import io.sphere.sdk.customergroups.commands.CustomerGroupCreateCommand; -import io.sphere.sdk.models.AssetDraft; -import io.sphere.sdk.models.AssetDraftBuilder; -import io.sphere.sdk.models.AssetSourceBuilder; -import io.sphere.sdk.models.LocalizedString; -import io.sphere.sdk.models.ResourceIdentifier; -import io.sphere.sdk.models.TextInputHint; -import io.sphere.sdk.products.Price; -import io.sphere.sdk.products.PriceDraft; -import io.sphere.sdk.products.PriceDraftBuilder; -import io.sphere.sdk.products.ProductDraft; -import io.sphere.sdk.products.ProductDraftBuilder; -import io.sphere.sdk.products.ProductVariantDraft; -import io.sphere.sdk.products.ProductVariantDraftBuilder; -import io.sphere.sdk.products.commands.ProductCreateCommand; -import io.sphere.sdk.producttypes.ProductType; -import io.sphere.sdk.producttypes.ProductTypeDraft; -import io.sphere.sdk.producttypes.ProductTypeDraftBuilder; -import io.sphere.sdk.producttypes.commands.ProductTypeCreateCommand; -import io.sphere.sdk.queries.PagedQueryResult; -import io.sphere.sdk.queries.QueryPredicate; -import io.sphere.sdk.states.State; -import io.sphere.sdk.states.StateDraft; -import io.sphere.sdk.states.StateDraftBuilder; -import io.sphere.sdk.states.StateType; -import io.sphere.sdk.states.commands.StateCreateCommand; -import io.sphere.sdk.taxcategories.TaxCategory; -import io.sphere.sdk.taxcategories.TaxCategoryDraft; -import io.sphere.sdk.taxcategories.TaxCategoryDraftBuilder; -import io.sphere.sdk.taxcategories.TaxRateDraft; -import io.sphere.sdk.taxcategories.TaxRateDraftBuilder; -import io.sphere.sdk.taxcategories.commands.TaxCategoryCreateCommand; -import io.sphere.sdk.taxcategories.queries.TaxCategoryQuery; -import io.sphere.sdk.types.CustomFieldsDraft; -import io.sphere.sdk.types.FieldDefinition; -import io.sphere.sdk.types.ResourceTypeIdsSetBuilder; -import io.sphere.sdk.types.StringFieldType; -import io.sphere.sdk.types.Type; -import io.sphere.sdk.types.TypeDraft; -import io.sphere.sdk.types.TypeDraftBuilder; -import io.sphere.sdk.types.commands.TypeCreateCommand; -import java.math.BigDecimal; -import java.time.ZonedDateTime; -import java.util.Arrays; -import java.util.Collections; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import javax.money.CurrencyUnit; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import uk.org.lidalia.slf4jext.Level; -import uk.org.lidalia.slf4jtest.TestLogger; -import uk.org.lidalia.slf4jtest.TestLoggerFactory; - -// This will suppress MoreThanOneLogger warnings in this class -@SuppressWarnings("PMD.MoreThanOneLogger") -public class ProductSyncWithReferenceResolutionIT { - - private static final TestLogger cliRunnerTestLogger = - TestLoggerFactory.getTestLogger(CliRunner.class); - private static final TestLogger productSyncerTestLogger = - TestLoggerFactory.getTestLogger(ProductSyncer.class); - private static final String RESOURCE_KEY = "foo"; - private static final String TYPE_KEY = "typeKey"; - - @BeforeEach - void setup() { - cliRunnerTestLogger.clearAll(); - productSyncerTestLogger.clearAll(); - cleanUpProjects(CTP_SOURCE_CLIENT, CTP_TARGET_CLIENT); - setupSourceProjectData(CTP_SOURCE_CLIENT); - } - - private void setupSourceProjectData(SphereClient sourceProjectClient) { - final ProductTypeDraft productTypeDraft = - ProductTypeDraftBuilder.of( - RESOURCE_KEY, "sample-product-type", "a productType for t-shirts", emptyList()) - .build(); - - final ProductType productType = - sourceProjectClient - .execute(ProductTypeCreateCommand.of(productTypeDraft)) - .toCompletableFuture() - .join(); - - final FieldDefinition FIELD_DEFINITION_1 = - FieldDefinition.of( - StringFieldType.of(), - "field_name_1", - LocalizedString.ofEnglish("label_1"), - false, - TextInputHint.SINGLE_LINE); - - final TypeDraft typeDraft = - TypeDraftBuilder.of( - TYPE_KEY, - LocalizedString.ofEnglish("name_1"), - ResourceTypeIdsSetBuilder.of().addCategories().addPrices().addAssets().build()) - .description(LocalizedString.ofEnglish("description_1")) - .fieldDefinitions(Arrays.asList(FIELD_DEFINITION_1)) - .build(); - - final Type type = - sourceProjectClient.execute(TypeCreateCommand.of(typeDraft)).toCompletableFuture().join(); - - final CategoryDraft categoryDraft = - CategoryDraftBuilder.of(ofEnglish("t-shirts"), ofEnglish("t-shirts")) - .key(RESOURCE_KEY) - .build(); - - sourceProjectClient - .execute(CategoryCreateCommand.of(categoryDraft)) - .toCompletableFuture() - .join(); - - final StateDraft stateDraft = - StateDraftBuilder.of(RESOURCE_KEY, StateType.PRODUCT_STATE) - .roles(Collections.emptySet()) - .description(ofEnglish("State 1")) - .name(ofEnglish("State 1")) - .initial(true) - .transitions(Collections.emptySet()) - .build(); - final State state = - sourceProjectClient.execute(StateCreateCommand.of(stateDraft)).toCompletableFuture().join(); - - final TaxRateDraft taxRateDraft = - TaxRateDraftBuilder.of("Tax-Rate-Name-1", 0.3, false, CountryCode.DE).build(); - - final TaxCategoryDraft taxCategoryDraft = - TaxCategoryDraftBuilder.of( - "Tax-Category-Name-1", singletonList(taxRateDraft), "Tax-Category-Description-1") - .key(RESOURCE_KEY) - .build(); - - final TaxCategory taxCategory = - sourceProjectClient - .execute(TaxCategoryCreateCommand.of(taxCategoryDraft)) - .toCompletableFuture() - .join(); - - final CustomerGroupDraft customerGroupDraft = - CustomerGroupDraftBuilder.of("customerGroupName").key("customerGroupKey").build(); - - CustomerGroup customerGroup = - sourceProjectClient - .execute(CustomerGroupCreateCommand.of(customerGroupDraft)) - .toCompletableFuture() - .join(); - - CTP_TARGET_CLIENT - .execute(CustomerGroupCreateCommand.of(customerGroupDraft)) - .toCompletableFuture() - .join(); - - CustomFieldsDraft customFieldsDraft = - CustomFieldsDraft.ofTypeKeyAndJson(type.getKey(), emptyMap()); - - final ChannelDraft draft = - ChannelDraftBuilder.of("channelKey").roles(singleton(ChannelRole.INVENTORY_SUPPLY)).build(); - sourceProjectClient.execute(ChannelCreateCommand.of(draft)).toCompletableFuture().join(); - CTP_TARGET_CLIENT.execute(ChannelCreateCommand.of(draft)).toCompletableFuture().join(); - - final PriceDraft priceBuilder = - PriceDraftBuilder.of( - getPriceDraft( - BigDecimal.valueOf(222), - EUR, - DE, - customerGroup.getId(), - null, - null, - null, - null)) - .customerGroup(customerGroup) - .custom(customFieldsDraft) - .channel(ResourceIdentifier.ofKey("channelKey")) - .build(); - - final AssetDraft assetDraft = - AssetDraftBuilder.of(emptyList(), LocalizedString.ofEnglish("assetName")) - .key("assetKey") - .sources(singletonList(AssetSourceBuilder.ofUri("sourceUri").build())) - .custom(customFieldsDraft) - .build(); - - final ProductVariantDraft variantDraft1 = - ProductVariantDraftBuilder.of() - .key("variantKey") - .sku("sku1") - .prices(priceBuilder) - .assets(asList(assetDraft)) - .build(); - - final ProductDraft productDraft = - ProductDraftBuilder.of( - productType, - ofEnglish("V-neck Tee"), - ofEnglish("v-neck-tee"), - ProductVariantDraftBuilder.of().key(RESOURCE_KEY).sku(RESOURCE_KEY).build()) - .state(State.referenceOfId(state.getId())) - .taxCategory(TaxCategory.referenceOfId(taxCategory.getId())) - .productType(ProductType.referenceOfId(productType.getId())) - .variants(asList(variantDraft1)) - .key(RESOURCE_KEY) - .publish(true) - .build(); - - sourceProjectClient.execute(ProductCreateCommand.of(productDraft)).toCompletableFuture().join(); - } - - @AfterAll - static void tearDownSuite() { - cleanUpProjects(CTP_SOURCE_CLIENT, CTP_TARGET_CLIENT); - } - - @Test - void run_WithSyncAsArgumentWithAllArgAsFullSync_ShouldResolveReferencesAndExecuteSyncers() { - // test - CliRunner.of().run(new String[] {"-s", "all", "-f"}, createITSyncerFactory()); - // assertions - assertThat(cliRunnerTestLogger.getAllLoggingEvents()) - .allMatch(loggingEvent -> !Level.ERROR.equals(loggingEvent.getLevel())); - - assertThat(productSyncerTestLogger.getAllLoggingEvents()) - .allMatch(loggingEvent -> !Level.ERROR.equals(loggingEvent.getLevel())); - - assertAllResourcesAreSyncedToTarget(CTP_TARGET_CLIENT); - } - - private static void assertAllResourcesAreSyncedToTarget( - @Nonnull final SphereClient targetClient) { - - assertProductTypeExists(targetClient, RESOURCE_KEY); - assertCategoryExists(targetClient, RESOURCE_KEY); - assertProductExists(targetClient, RESOURCE_KEY, RESOURCE_KEY, RESOURCE_KEY); - - final String queryPredicate = format("key=\"%s\"", RESOURCE_KEY); - - final PagedQueryResult taxCategoryQueryResult = - targetClient - .execute(TaxCategoryQuery.of().withPredicates(QueryPredicate.of(queryPredicate))) - .toCompletableFuture() - .join(); - assertThat(taxCategoryQueryResult.getResults()) - .hasSize(1) - .singleElement() - .satisfies(taxCategory -> assertThat(taxCategory.getKey()).isEqualTo(RESOURCE_KEY)); - } - - @Nonnull - public static PriceDraft getPriceDraft( - @Nonnull final BigDecimal value, - @Nonnull final CurrencyUnit currencyUnits, - @Nullable final CountryCode countryCode, - @Nullable final String customerGroupId, - @Nullable final ZonedDateTime validFrom, - @Nullable final ZonedDateTime validUntil, - @Nullable final String channelId, - @Nullable final CustomFieldsDraft customFieldsDraft) { - return PriceDraftBuilder.of(Price.of(value, currencyUnits)) - .country(countryCode) - .customerGroup( - ofNullable(customerGroupId).map(ResourceIdentifier::ofId).orElse(null)) - .validFrom(validFrom) - .validUntil(validUntil) - .channel(ofNullable(channelId).map(ResourceIdentifier::ofId).orElse(null)) - .custom(customFieldsDraft) - .build(); - } -} +// package com.commercetools.project.sync; +// +// import static com.commercetools.project.sync.util.CtpClientUtils.CTP_SOURCE_CLIENT; +// import static com.commercetools.project.sync.util.CtpClientUtils.CTP_TARGET_CLIENT; +// import static com.commercetools.project.sync.util.IntegrationTestUtils.assertCategoryExists; +// import static com.commercetools.project.sync.util.IntegrationTestUtils.assertProductExists; +// import static com.commercetools.project.sync.util.IntegrationTestUtils.assertProductTypeExists; +// import static com.commercetools.project.sync.util.IntegrationTestUtils.cleanUpProjects; +// import static com.commercetools.project.sync.util.IntegrationTestUtils.createITSyncerFactory; +// import static com.neovisionaries.i18n.CountryCode.DE; +// import static io.sphere.sdk.models.DefaultCurrencyUnits.EUR; +// import static io.sphere.sdk.models.LocalizedString.ofEnglish; +// import static java.lang.String.format; +// import static java.util.Arrays.asList; +// import static java.util.Collections.emptyList; +// import static java.util.Collections.emptyMap; +// import static java.util.Collections.singleton; +// import static java.util.Collections.singletonList; +// import static java.util.Optional.ofNullable; +// import static org.assertj.core.api.Assertions.assertThat; +// +// import com.commercetools.project.sync.product.ProductSyncer; +// import com.neovisionaries.i18n.CountryCode; +// import io.sphere.sdk.categories.CategoryDraft; +// import io.sphere.sdk.categories.CategoryDraftBuilder; +// import io.sphere.sdk.categories.commands.CategoryCreateCommand; +// import io.sphere.sdk.channels.Channel; +// import io.sphere.sdk.channels.ChannelDraft; +// import io.sphere.sdk.channels.ChannelDraftBuilder; +// import io.sphere.sdk.channels.ChannelRole; +// import io.sphere.sdk.channels.commands.ChannelCreateCommand; +// import io.sphere.sdk.client.SphereClient; +// import io.sphere.sdk.customergroups.CustomerGroup; +// import io.sphere.sdk.customergroups.CustomerGroupDraft; +// import io.sphere.sdk.customergroups.CustomerGroupDraftBuilder; +// import io.sphere.sdk.customergroups.commands.CustomerGroupCreateCommand; +// import io.sphere.sdk.models.AssetDraft; +// import io.sphere.sdk.models.AssetDraftBuilder; +// import io.sphere.sdk.models.AssetSourceBuilder; +// import io.sphere.sdk.models.LocalizedString; +// import io.sphere.sdk.models.ResourceIdentifier; +// import io.sphere.sdk.models.TextInputHint; +// import io.sphere.sdk.products.Price; +// import io.sphere.sdk.products.PriceDraft; +// import io.sphere.sdk.products.PriceDraftBuilder; +// import io.sphere.sdk.products.ProductDraft; +// import io.sphere.sdk.products.ProductDraftBuilder; +// import io.sphere.sdk.products.ProductVariantDraft; +// import io.sphere.sdk.products.ProductVariantDraftBuilder; +// import io.sphere.sdk.products.commands.ProductCreateCommand; +// import io.sphere.sdk.producttypes.ProductType; +// import io.sphere.sdk.producttypes.ProductTypeDraft; +// import io.sphere.sdk.producttypes.ProductTypeDraftBuilder; +// import io.sphere.sdk.producttypes.commands.ProductTypeCreateCommand; +// import io.sphere.sdk.queries.PagedQueryResult; +// import io.sphere.sdk.queries.QueryPredicate; +// import io.sphere.sdk.states.State; +// import io.sphere.sdk.states.StateDraft; +// import io.sphere.sdk.states.StateDraftBuilder; +// import io.sphere.sdk.states.StateType; +// import io.sphere.sdk.states.commands.StateCreateCommand; +// import io.sphere.sdk.taxcategories.TaxCategory; +// import io.sphere.sdk.taxcategories.TaxCategoryDraft; +// import io.sphere.sdk.taxcategories.TaxCategoryDraftBuilder; +// import io.sphere.sdk.taxcategories.TaxRateDraft; +// import io.sphere.sdk.taxcategories.TaxRateDraftBuilder; +// import io.sphere.sdk.taxcategories.commands.TaxCategoryCreateCommand; +// import io.sphere.sdk.taxcategories.queries.TaxCategoryQuery; +// import io.sphere.sdk.types.CustomFieldsDraft; +// import io.sphere.sdk.types.FieldDefinition; +// import io.sphere.sdk.types.ResourceTypeIdsSetBuilder; +// import io.sphere.sdk.types.StringFieldType; +// import io.sphere.sdk.types.Type; +// import io.sphere.sdk.types.TypeDraft; +// import io.sphere.sdk.types.TypeDraftBuilder; +// import io.sphere.sdk.types.commands.TypeCreateCommand; +// import java.math.BigDecimal; +// import java.time.ZonedDateTime; +// import java.util.Arrays; +// import java.util.Collections; +// import javax.annotation.Nonnull; +// import javax.annotation.Nullable; +// import javax.money.CurrencyUnit; +// import org.junit.jupiter.api.AfterAll; +// import org.junit.jupiter.api.BeforeEach; +// import org.junit.jupiter.api.Test; +// import uk.org.lidalia.slf4jext.Level; +// import uk.org.lidalia.slf4jtest.TestLogger; +// import uk.org.lidalia.slf4jtest.TestLoggerFactory; +// +//// This will suppress MoreThanOneLogger warnings in this class +// @SuppressWarnings("PMD.MoreThanOneLogger") +// public class ProductSyncWithReferenceResolutionIT { +// +// private static final TestLogger cliRunnerTestLogger = +// TestLoggerFactory.getTestLogger(CliRunner.class); +// private static final TestLogger productSyncerTestLogger = +// TestLoggerFactory.getTestLogger(ProductSyncer.class); +// private static final String RESOURCE_KEY = "foo"; +// private static final String TYPE_KEY = "typeKey"; +// +// @BeforeEach +// void setup() { +// cliRunnerTestLogger.clearAll(); +// productSyncerTestLogger.clearAll(); +// cleanUpProjects(CTP_SOURCE_CLIENT, CTP_TARGET_CLIENT); +// setupSourceProjectData(CTP_SOURCE_CLIENT); +// } +// +// private void setupSourceProjectData(SphereClient sourceProjectClient) { +// final ProductTypeDraft productTypeDraft = +// ProductTypeDraftBuilder.of( +// RESOURCE_KEY, "sample-product-type", "a productType for t-shirts", emptyList()) +// .build(); +// +// final ProductType productType = +// sourceProjectClient +// .execute(ProductTypeCreateCommand.of(productTypeDraft)) +// .toCompletableFuture() +// .join(); +// +// final FieldDefinition FIELD_DEFINITION_1 = +// FieldDefinition.of( +// StringFieldType.of(), +// "field_name_1", +// LocalizedString.ofEnglish("label_1"), +// false, +// TextInputHint.SINGLE_LINE); +// +// final TypeDraft typeDraft = +// TypeDraftBuilder.of( +// TYPE_KEY, +// LocalizedString.ofEnglish("name_1"), +// ResourceTypeIdsSetBuilder.of().addCategories().addPrices().addAssets().build()) +// .description(LocalizedString.ofEnglish("description_1")) +// .fieldDefinitions(Arrays.asList(FIELD_DEFINITION_1)) +// .build(); +// +// final Type type = +// sourceProjectClient.execute(TypeCreateCommand.of(typeDraft)).toCompletableFuture().join(); +// +// final CategoryDraft categoryDraft = +// CategoryDraftBuilder.of(ofEnglish("t-shirts"), ofEnglish("t-shirts")) +// .key(RESOURCE_KEY) +// .build(); +// +// sourceProjectClient +// .execute(CategoryCreateCommand.of(categoryDraft)) +// .toCompletableFuture() +// .join(); +// +// final StateDraft stateDraft = +// StateDraftBuilder.of(RESOURCE_KEY, StateType.PRODUCT_STATE) +// .roles(Collections.emptySet()) +// .description(ofEnglish("State 1")) +// .name(ofEnglish("State 1")) +// .initial(true) +// .transitions(Collections.emptySet()) +// .build(); +// final State state = +// +// sourceProjectClient.execute(StateCreateCommand.of(stateDraft)).toCompletableFuture().join(); +// +// final TaxRateDraft taxRateDraft = +// TaxRateDraftBuilder.of("Tax-Rate-Name-1", 0.3, false, CountryCode.DE).build(); +// +// final TaxCategoryDraft taxCategoryDraft = +// TaxCategoryDraftBuilder.of( +// "Tax-Category-Name-1", singletonList(taxRateDraft), "Tax-Category-Description-1") +// .key(RESOURCE_KEY) +// .build(); +// +// final TaxCategory taxCategory = +// sourceProjectClient +// .execute(TaxCategoryCreateCommand.of(taxCategoryDraft)) +// .toCompletableFuture() +// .join(); +// +// final CustomerGroupDraft customerGroupDraft = +// CustomerGroupDraftBuilder.of("customerGroupName").key("customerGroupKey").build(); +// +// CustomerGroup customerGroup = +// sourceProjectClient +// .execute(CustomerGroupCreateCommand.of(customerGroupDraft)) +// .toCompletableFuture() +// .join(); +// +// CTP_TARGET_CLIENT +// .execute(CustomerGroupCreateCommand.of(customerGroupDraft)) +// .toCompletableFuture() +// .join(); +// +// CustomFieldsDraft customFieldsDraft = +// CustomFieldsDraft.ofTypeKeyAndJson(type.getKey(), emptyMap()); +// +// final ChannelDraft draft = +// +// ChannelDraftBuilder.of("channelKey").roles(singleton(ChannelRole.INVENTORY_SUPPLY)).build(); +// sourceProjectClient.execute(ChannelCreateCommand.of(draft)).toCompletableFuture().join(); +// CTP_TARGET_CLIENT.execute(ChannelCreateCommand.of(draft)).toCompletableFuture().join(); +// +// final PriceDraft priceBuilder = +// PriceDraftBuilder.of( +// getPriceDraft( +// BigDecimal.valueOf(222), +// EUR, +// DE, +// customerGroup.getId(), +// null, +// null, +// null, +// null)) +// .customerGroup(customerGroup) +// .custom(customFieldsDraft) +// .channel(ResourceIdentifier.ofKey("channelKey")) +// .build(); +// +// final AssetDraft assetDraft = +// AssetDraftBuilder.of(emptyList(), LocalizedString.ofEnglish("assetName")) +// .key("assetKey") +// .sources(singletonList(AssetSourceBuilder.ofUri("sourceUri").build())) +// .custom(customFieldsDraft) +// .build(); +// +// final ProductVariantDraft variantDraft1 = +// ProductVariantDraftBuilder.of() +// .key("variantKey") +// .sku("sku1") +// .prices(priceBuilder) +// .assets(asList(assetDraft)) +// .build(); +// +// final ProductDraft productDraft = +// ProductDraftBuilder.of( +// productType, +// ofEnglish("V-neck Tee"), +// ofEnglish("v-neck-tee"), +// ProductVariantDraftBuilder.of().key(RESOURCE_KEY).sku(RESOURCE_KEY).build()) +// .state(State.referenceOfId(state.getId())) +// .taxCategory(TaxCategory.referenceOfId(taxCategory.getId())) +// .productType(ProductType.referenceOfId(productType.getId())) +// .variants(asList(variantDraft1)) +// .key(RESOURCE_KEY) +// .publish(true) +// .build(); +// +// +// sourceProjectClient.execute(ProductCreateCommand.of(productDraft)).toCompletableFuture().join(); +// } +// +// @AfterAll +// static void tearDownSuite() { +// cleanUpProjects(CTP_SOURCE_CLIENT, CTP_TARGET_CLIENT); +// } +// +// @Test +// void run_WithSyncAsArgumentWithAllArgAsFullSync_ShouldResolveReferencesAndExecuteSyncers() { +// // test +// CliRunner.of().run(new String[] {"-s", "all", "-f"}, createITSyncerFactory()); +// // assertions +// assertThat(cliRunnerTestLogger.getAllLoggingEvents()) +// .allMatch(loggingEvent -> !Level.ERROR.equals(loggingEvent.getLevel())); +// +// assertThat(productSyncerTestLogger.getAllLoggingEvents()) +// .allMatch(loggingEvent -> !Level.ERROR.equals(loggingEvent.getLevel())); +// +// assertAllResourcesAreSyncedToTarget(CTP_TARGET_CLIENT); +// } +// +// private static void assertAllResourcesAreSyncedToTarget( +// @Nonnull final SphereClient targetClient) { +// +// assertProductTypeExists(targetClient, RESOURCE_KEY); +// assertCategoryExists(targetClient, RESOURCE_KEY); +// assertProductExists(targetClient, RESOURCE_KEY, RESOURCE_KEY, RESOURCE_KEY); +// +// final String queryPredicate = format("key=\"%s\"", RESOURCE_KEY); +// +// final PagedQueryResult taxCategoryQueryResult = +// targetClient +// .execute(TaxCategoryQuery.of().withPredicates(QueryPredicate.of(queryPredicate))) +// .toCompletableFuture() +// .join(); +// assertThat(taxCategoryQueryResult.getResults()) +// .hasSize(1) +// .singleElement() +// .satisfies(taxCategory -> assertThat(taxCategory.getKey()).isEqualTo(RESOURCE_KEY)); +// } +// +// @Nonnull +// public static PriceDraft getPriceDraft( +// @Nonnull final BigDecimal value, +// @Nonnull final CurrencyUnit currencyUnits, +// @Nullable final CountryCode countryCode, +// @Nullable final String customerGroupId, +// @Nullable final ZonedDateTime validFrom, +// @Nullable final ZonedDateTime validUntil, +// @Nullable final String channelId, +// @Nullable final CustomFieldsDraft customFieldsDraft) { +// return PriceDraftBuilder.of(Price.of(value, currencyUnits)) +// .country(countryCode) +// .customerGroup( +// ofNullable(customerGroupId).map(ResourceIdentifier::ofId).orElse(null)) +// .validFrom(validFrom) +// .validUntil(validUntil) +// .channel(ofNullable(channelId).map(ResourceIdentifier::ofId).orElse(null)) +// .custom(customFieldsDraft) +// .build(); +// } +// } diff --git a/src/integration-test/java/com/commercetools/project/sync/ProductSyncWithReferencesIT.java b/src/integration-test/java/com/commercetools/project/sync/ProductSyncWithReferencesIT.java index 87d33306..7a7bf0b9 100644 --- a/src/integration-test/java/com/commercetools/project/sync/ProductSyncWithReferencesIT.java +++ b/src/integration-test/java/com/commercetools/project/sync/ProductSyncWithReferencesIT.java @@ -1,265 +1,270 @@ -package com.commercetools.project.sync; - -import static com.commercetools.project.sync.util.CtpClientUtils.CTP_SOURCE_CLIENT; -import static com.commercetools.project.sync.util.CtpClientUtils.CTP_TARGET_CLIENT; -import static com.commercetools.project.sync.util.IntegrationTestUtils.assertProductTypeExists; -import static com.commercetools.project.sync.util.IntegrationTestUtils.cleanUpProjects; -import static com.commercetools.project.sync.util.IntegrationTestUtils.createITSyncerFactory; -import static com.commercetools.project.sync.util.IntegrationTestUtils.createReferenceObject; -import static com.commercetools.project.sync.util.TestUtils.assertCartDiscountSyncerLoggingEvents; -import static com.commercetools.project.sync.util.TestUtils.assertCategorySyncerLoggingEvents; -import static com.commercetools.project.sync.util.TestUtils.assertCustomObjectSyncerLoggingEvents; -import static com.commercetools.project.sync.util.TestUtils.assertCustomerSyncerLoggingEvents; -import static com.commercetools.project.sync.util.TestUtils.assertInventoryEntrySyncerLoggingEvents; -import static com.commercetools.project.sync.util.TestUtils.assertProductSyncerLoggingEvents; -import static com.commercetools.project.sync.util.TestUtils.assertProductTypeSyncerLoggingEvents; -import static com.commercetools.project.sync.util.TestUtils.assertShoppingListSyncerLoggingEvents; -import static com.commercetools.project.sync.util.TestUtils.assertStateSyncerLoggingEvents; -import static com.commercetools.project.sync.util.TestUtils.assertTaxCategorySyncerLoggingEvents; -import static com.commercetools.project.sync.util.TestUtils.assertTypeSyncerLoggingEvents; -import static io.sphere.sdk.models.LocalizedString.ofEnglish; -import static java.lang.String.format; -import static java.util.Collections.emptyList; -import static java.util.Collections.singletonList; -import static org.assertj.core.api.Assertions.assertThat; - -import com.commercetools.project.sync.cartdiscount.CartDiscountSyncer; -import com.commercetools.project.sync.category.CategorySyncer; -import com.commercetools.project.sync.customer.CustomerSyncer; -import com.commercetools.project.sync.customobject.CustomObjectSyncer; -import com.commercetools.project.sync.inventoryentry.InventoryEntrySyncer; -import com.commercetools.project.sync.product.ProductSyncer; -import com.commercetools.project.sync.producttype.ProductTypeSyncer; -import com.commercetools.project.sync.shoppinglist.ShoppingListSyncer; -import com.commercetools.project.sync.state.StateSyncer; -import com.commercetools.project.sync.taxcategory.TaxCategorySyncer; -import com.commercetools.project.sync.type.TypeSyncer; -import com.commercetools.sync.commons.models.WaitingToBeResolved; -import com.commercetools.sync.commons.utils.CtpQueryUtils; -import com.fasterxml.jackson.databind.node.ArrayNode; -import com.fasterxml.jackson.databind.node.JsonNodeFactory; -import com.fasterxml.jackson.databind.node.ObjectNode; -import io.sphere.sdk.client.SphereClient; -import io.sphere.sdk.customobjects.CustomObject; -import io.sphere.sdk.customobjects.queries.CustomObjectQuery; -import io.sphere.sdk.products.Product; -import io.sphere.sdk.products.ProductDraft; -import io.sphere.sdk.products.ProductDraftBuilder; -import io.sphere.sdk.products.ProductVariantDraft; -import io.sphere.sdk.products.ProductVariantDraftBuilder; -import io.sphere.sdk.products.attributes.AttributeConstraint; -import io.sphere.sdk.products.attributes.AttributeDefinitionDraft; -import io.sphere.sdk.products.attributes.AttributeDefinitionDraftBuilder; -import io.sphere.sdk.products.attributes.AttributeDraft; -import io.sphere.sdk.products.attributes.ReferenceAttributeType; -import io.sphere.sdk.products.attributes.SetAttributeType; -import io.sphere.sdk.products.commands.ProductCreateCommand; -import io.sphere.sdk.products.queries.ProductQuery; -import io.sphere.sdk.producttypes.ProductType; -import io.sphere.sdk.producttypes.ProductTypeDraft; -import io.sphere.sdk.producttypes.ProductTypeDraftBuilder; -import io.sphere.sdk.producttypes.commands.ProductTypeCreateCommand; -import io.sphere.sdk.queries.PagedQueryResult; -import java.util.List; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ConcurrentHashMap; -import java.util.function.Function; -import java.util.stream.Collectors; -import java.util.stream.IntStream; -import javax.annotation.Nonnull; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import uk.org.lidalia.slf4jext.Level; -import uk.org.lidalia.slf4jtest.TestLogger; -import uk.org.lidalia.slf4jtest.TestLoggerFactory; - -// This will suppress MoreThanOneLogger warnings in this class -@SuppressWarnings("PMD.MoreThanOneLogger") -class ProductSyncWithReferencesIT { - - private static final TestLogger productSyncerTestLogger = - TestLoggerFactory.getTestLogger(ProductSyncer.class); - private static final TestLogger cliRunnerTestLogger = - TestLoggerFactory.getTestLogger(CliRunner.class); - private static final TestLogger productTypeSyncerTestLogger = - TestLoggerFactory.getTestLogger(ProductTypeSyncer.class); - private static final TestLogger customerSyncerTestLogger = - TestLoggerFactory.getTestLogger(CustomerSyncer.class); - private static final TestLogger shoppingListSyncerTestLogger = - TestLoggerFactory.getTestLogger(ShoppingListSyncer.class); - private static final TestLogger stateSyncerTestLogger = - TestLoggerFactory.getTestLogger(StateSyncer.class); - private static final TestLogger inventoryEntrySyncerTestLogger = - TestLoggerFactory.getTestLogger(InventoryEntrySyncer.class); - private static final TestLogger customObjectSyncerTestLogger = - TestLoggerFactory.getTestLogger(CustomObjectSyncer.class); - private static final TestLogger typeSyncerTestLogger = - TestLoggerFactory.getTestLogger(TypeSyncer.class); - private static final TestLogger categorySyncerTestLogger = - TestLoggerFactory.getTestLogger(CategorySyncer.class); - private static final TestLogger cartDiscountSyncerTestLogger = - TestLoggerFactory.getTestLogger(CartDiscountSyncer.class); - private static final TestLogger taxCategorySyncerTestLogger = - TestLoggerFactory.getTestLogger(TaxCategorySyncer.class); - - private static final String MAIN_PRODUCT_TYPE_KEY = "main-product-type"; - private static final String MAIN_PRODUCT_MASTER_VARIANT_KEY = "main-product-master-variant-key"; - private static final String MAIN_PRODUCT_KEY = "product-with-references"; - - @BeforeEach - void setup() { - cliRunnerTestLogger.clearAll(); - productSyncerTestLogger.clearAll(); - productTypeSyncerTestLogger.clearAll(); - customerSyncerTestLogger.clearAll(); - shoppingListSyncerTestLogger.clearAll(); - stateSyncerTestLogger.clearAll(); - inventoryEntrySyncerTestLogger.clearAll(); - customObjectSyncerTestLogger.clearAll(); - typeSyncerTestLogger.clearAll(); - categorySyncerTestLogger.clearAll(); - cartDiscountSyncerTestLogger.clearAll(); - taxCategorySyncerTestLogger.clearAll(); - cleanUpProjects(CTP_SOURCE_CLIENT, CTP_TARGET_CLIENT); - setupSourceProjectData(CTP_SOURCE_CLIENT); - } - - static void setupSourceProjectData(@Nonnull final SphereClient sourceProjectClient) { - final AttributeDefinitionDraft setOfProductsAttributeDef = - AttributeDefinitionDraftBuilder.of( - SetAttributeType.of(ReferenceAttributeType.ofProduct()), - "products", - ofEnglish("products"), - false) - .searchable(false) - .attributeConstraint(AttributeConstraint.NONE) - .build(); - - final ProductTypeDraft productTypeDraft = - ProductTypeDraftBuilder.of( - MAIN_PRODUCT_TYPE_KEY, - MAIN_PRODUCT_TYPE_KEY, - "a productType for t-shirts", - emptyList()) - .attributes(singletonList(setOfProductsAttributeDef)) - .build(); - - final ProductType productType = - sourceProjectClient - .execute(ProductTypeCreateCommand.of(productTypeDraft)) - .toCompletableFuture() - .join(); - - final ConcurrentHashMap.KeySetView productIds = ConcurrentHashMap.newKeySet(); - - // create 500 products - final CompletableFuture[] creationFutures = - IntStream.range(0, 500) - .mapToObj( - index -> { - final ProductVariantDraft masterVariant = - ProductVariantDraftBuilder.of() - .key(format("%d-mv-key", index)) - .sku(format("%d-mv-sku", index)) - .build(); - - final ProductDraft draft = - ProductDraftBuilder.of( - productType, - ofEnglish(Integer.toString(index)), - ofEnglish(format("%d-slug", index)), - masterVariant) - .key(format("%d-key", index)) - .build(); - return CTP_SOURCE_CLIENT - .execute(ProductCreateCommand.of(draft)) - .thenAccept(createdProduct -> productIds.add(createdProduct.getId())) - .toCompletableFuture(); - }) - .toArray(CompletableFuture[]::new); - - CompletableFuture.allOf(creationFutures).join(); - - final ArrayNode setAttributeValue = JsonNodeFactory.instance.arrayNode(); - final Set productReferences = - productIds.stream() - .map(productId -> createReferenceObject(Product.referenceTypeId(), productId)) - .collect(Collectors.toSet()); - setAttributeValue.addAll(productReferences); - - final ProductVariantDraft masterVariant = - ProductVariantDraftBuilder.of() - .key(MAIN_PRODUCT_MASTER_VARIANT_KEY) - .sku(MAIN_PRODUCT_MASTER_VARIANT_KEY) - .attributes(AttributeDraft.of(setOfProductsAttributeDef.getName(), setAttributeValue)) - .build(); - - final ProductDraft draft = - ProductDraftBuilder.of( - productType, - ofEnglish(MAIN_PRODUCT_KEY), - ofEnglish(MAIN_PRODUCT_KEY), - masterVariant) - .key(MAIN_PRODUCT_KEY) - .build(); - - sourceProjectClient.execute(ProductCreateCommand.of(draft)).toCompletableFuture().join(); - } - - @AfterAll - static void tearDownSuite() { - cleanUpProjects(CTP_SOURCE_CLIENT, CTP_TARGET_CLIENT); - } - - @Test - void run_WithAProductWith500DistinctReferences_ShouldSyncCorrectly() { - // test - CliRunner.of() - .run(new String[] {"-s", "all", "-r", "runnerName", "-f"}, createITSyncerFactory()); - - // assertions - assertThat(cliRunnerTestLogger.getAllLoggingEvents()) - .allMatch(loggingEvent -> !Level.ERROR.equals(loggingEvent.getLevel())); - - assertTypeSyncerLoggingEvents(typeSyncerTestLogger, 0); - assertProductTypeSyncerLoggingEvents(productTypeSyncerTestLogger, 1); - assertTaxCategorySyncerLoggingEvents(taxCategorySyncerTestLogger, 0); - assertCategorySyncerLoggingEvents(categorySyncerTestLogger, 0); - assertProductSyncerLoggingEvents(productSyncerTestLogger, 501); - assertInventoryEntrySyncerLoggingEvents(inventoryEntrySyncerTestLogger, 0); - assertCartDiscountSyncerLoggingEvents(cartDiscountSyncerTestLogger, 0); - assertCustomerSyncerLoggingEvents(customerSyncerTestLogger, 0); - assertShoppingListSyncerLoggingEvents(shoppingListSyncerTestLogger, 0); - assertStateSyncerLoggingEvents( - stateSyncerTestLogger, 1); // 1 state is built-in and it cant be deleted - assertCustomObjectSyncerLoggingEvents(customObjectSyncerTestLogger, 0); - - assertAllResourcesAreSyncedToTarget(CTP_TARGET_CLIENT); - } - - private static void assertAllResourcesAreSyncedToTarget( - @Nonnull final SphereClient targetClient) { - - assertProductTypeExists(targetClient, MAIN_PRODUCT_TYPE_KEY); - - final List products = - CtpQueryUtils.queryAll(targetClient, ProductQuery.of(), Function.identity()) - .thenApply( - fetchedProducts -> - fetchedProducts.stream().flatMap(List::stream).collect(Collectors.toList())) - .toCompletableFuture() - .join(); - assertThat(products).hasSize(501); - - final CustomObjectQuery customObjectQuery = - CustomObjectQuery.of(WaitingToBeResolved.class) - .byContainer("commercetools-sync-java.UnresolvedReferencesService.productDrafts"); - - final PagedQueryResult> queryResult = - targetClient.execute(customObjectQuery).toCompletableFuture().join(); - - assertThat(queryResult.getResults()).isEmpty(); - } -} +// package com.commercetools.project.sync; +// +// import static com.commercetools.project.sync.util.CtpClientUtils.CTP_SOURCE_CLIENT; +// import static com.commercetools.project.sync.util.CtpClientUtils.CTP_TARGET_CLIENT; +// import static com.commercetools.project.sync.util.IntegrationTestUtils.assertProductTypeExists; +// import static com.commercetools.project.sync.util.IntegrationTestUtils.cleanUpProjects; +// import static com.commercetools.project.sync.util.IntegrationTestUtils.createITSyncerFactory; +// import static com.commercetools.project.sync.util.IntegrationTestUtils.createReferenceObject; +// import static +// com.commercetools.project.sync.util.TestUtils.assertCartDiscountSyncerLoggingEvents; +// import static com.commercetools.project.sync.util.TestUtils.assertCategorySyncerLoggingEvents; +// import static +// com.commercetools.project.sync.util.TestUtils.assertCustomObjectSyncerLoggingEvents; +// import static com.commercetools.project.sync.util.TestUtils.assertCustomerSyncerLoggingEvents; +// import static +// com.commercetools.project.sync.util.TestUtils.assertInventoryEntrySyncerLoggingEvents; +// import static com.commercetools.project.sync.util.TestUtils.assertProductSyncerLoggingEvents; +// import static com.commercetools.project.sync.util.TestUtils.assertProductTypeSyncerLoggingEvents; +// import static +// com.commercetools.project.sync.util.TestUtils.assertShoppingListSyncerLoggingEvents; +// import static com.commercetools.project.sync.util.TestUtils.assertStateSyncerLoggingEvents; +// import static com.commercetools.project.sync.util.TestUtils.assertTaxCategorySyncerLoggingEvents; +// import static com.commercetools.project.sync.util.TestUtils.assertTypeSyncerLoggingEvents; +// import static io.sphere.sdk.models.LocalizedString.ofEnglish; +// import static java.lang.String.format; +// import static java.util.Collections.emptyList; +// import static java.util.Collections.singletonList; +// import static org.assertj.core.api.Assertions.assertThat; +// +// import com.commercetools.project.sync.cartdiscount.CartDiscountSyncer; +// import com.commercetools.project.sync.category.CategorySyncer; +// import com.commercetools.project.sync.customer.CustomerSyncer; +// import com.commercetools.project.sync.customobject.CustomObjectSyncer; +// import com.commercetools.project.sync.inventoryentry.InventoryEntrySyncer; +// import com.commercetools.project.sync.product.ProductSyncer; +// import com.commercetools.project.sync.producttype.ProductTypeSyncer; +// import com.commercetools.project.sync.shoppinglist.ShoppingListSyncer; +// import com.commercetools.project.sync.state.StateSyncer; +// import com.commercetools.project.sync.taxcategory.TaxCategorySyncer; +// import com.commercetools.project.sync.type.TypeSyncer; +// import com.commercetools.sync.commons.models.WaitingToBeResolved; +// import com.commercetools.sync.commons.utils.CtpQueryUtils; +// import com.fasterxml.jackson.databind.node.ArrayNode; +// import com.fasterxml.jackson.databind.node.JsonNodeFactory; +// import com.fasterxml.jackson.databind.node.ObjectNode; +// import io.sphere.sdk.client.SphereClient; +// import io.sphere.sdk.customobjects.CustomObject; +// import io.sphere.sdk.customobjects.queries.CustomObjectQuery; +// import io.sphere.sdk.products.Product; +// import io.sphere.sdk.products.ProductDraft; +// import io.sphere.sdk.products.ProductDraftBuilder; +// import io.sphere.sdk.products.ProductVariantDraft; +// import io.sphere.sdk.products.ProductVariantDraftBuilder; +// import io.sphere.sdk.products.attributes.AttributeConstraint; +// import io.sphere.sdk.products.attributes.AttributeDefinitionDraft; +// import io.sphere.sdk.products.attributes.AttributeDefinitionDraftBuilder; +// import io.sphere.sdk.products.attributes.AttributeDraft; +// import io.sphere.sdk.products.attributes.ReferenceAttributeType; +// import io.sphere.sdk.products.attributes.SetAttributeType; +// import io.sphere.sdk.products.commands.ProductCreateCommand; +// import io.sphere.sdk.products.queries.ProductQuery; +// import io.sphere.sdk.producttypes.ProductType; +// import io.sphere.sdk.producttypes.ProductTypeDraft; +// import io.sphere.sdk.producttypes.ProductTypeDraftBuilder; +// import io.sphere.sdk.producttypes.commands.ProductTypeCreateCommand; +// import io.sphere.sdk.queries.PagedQueryResult; +// import java.util.List; +// import java.util.Set; +// import java.util.concurrent.CompletableFuture; +// import java.util.concurrent.ConcurrentHashMap; +// import java.util.function.Function; +// import java.util.stream.Collectors; +// import java.util.stream.IntStream; +// import javax.annotation.Nonnull; +// import org.junit.jupiter.api.AfterAll; +// import org.junit.jupiter.api.BeforeEach; +// import org.junit.jupiter.api.Test; +// import uk.org.lidalia.slf4jext.Level; +// import uk.org.lidalia.slf4jtest.TestLogger; +// import uk.org.lidalia.slf4jtest.TestLoggerFactory; +// +//// This will suppress MoreThanOneLogger warnings in this class +// @SuppressWarnings("PMD.MoreThanOneLogger") +// class ProductSyncWithReferencesIT { +// +// private static final TestLogger productSyncerTestLogger = +// TestLoggerFactory.getTestLogger(ProductSyncer.class); +// private static final TestLogger cliRunnerTestLogger = +// TestLoggerFactory.getTestLogger(CliRunner.class); +// private static final TestLogger productTypeSyncerTestLogger = +// TestLoggerFactory.getTestLogger(ProductTypeSyncer.class); +// private static final TestLogger customerSyncerTestLogger = +// TestLoggerFactory.getTestLogger(CustomerSyncer.class); +// private static final TestLogger shoppingListSyncerTestLogger = +// TestLoggerFactory.getTestLogger(ShoppingListSyncer.class); +// private static final TestLogger stateSyncerTestLogger = +// TestLoggerFactory.getTestLogger(StateSyncer.class); +// private static final TestLogger inventoryEntrySyncerTestLogger = +// TestLoggerFactory.getTestLogger(InventoryEntrySyncer.class); +// private static final TestLogger customObjectSyncerTestLogger = +// TestLoggerFactory.getTestLogger(CustomObjectSyncer.class); +// private static final TestLogger typeSyncerTestLogger = +// TestLoggerFactory.getTestLogger(TypeSyncer.class); +// private static final TestLogger categorySyncerTestLogger = +// TestLoggerFactory.getTestLogger(CategorySyncer.class); +// private static final TestLogger cartDiscountSyncerTestLogger = +// TestLoggerFactory.getTestLogger(CartDiscountSyncer.class); +// private static final TestLogger taxCategorySyncerTestLogger = +// TestLoggerFactory.getTestLogger(TaxCategorySyncer.class); +// +// private static final String MAIN_PRODUCT_TYPE_KEY = "main-product-type"; +// private static final String MAIN_PRODUCT_MASTER_VARIANT_KEY = "main-product-master-variant-key"; +// private static final String MAIN_PRODUCT_KEY = "product-with-references"; +// +// @BeforeEach +// void setup() { +// cliRunnerTestLogger.clearAll(); +// productSyncerTestLogger.clearAll(); +// productTypeSyncerTestLogger.clearAll(); +// customerSyncerTestLogger.clearAll(); +// shoppingListSyncerTestLogger.clearAll(); +// stateSyncerTestLogger.clearAll(); +// inventoryEntrySyncerTestLogger.clearAll(); +// customObjectSyncerTestLogger.clearAll(); +// typeSyncerTestLogger.clearAll(); +// categorySyncerTestLogger.clearAll(); +// cartDiscountSyncerTestLogger.clearAll(); +// taxCategorySyncerTestLogger.clearAll(); +// cleanUpProjects(CTP_SOURCE_CLIENT, CTP_TARGET_CLIENT); +// setupSourceProjectData(CTP_SOURCE_CLIENT); +// } +// +// static void setupSourceProjectData(@Nonnull final SphereClient sourceProjectClient) { +// final AttributeDefinitionDraft setOfProductsAttributeDef = +// AttributeDefinitionDraftBuilder.of( +// SetAttributeType.of(ReferenceAttributeType.ofProduct()), +// "products", +// ofEnglish("products"), +// false) +// .searchable(false) +// .attributeConstraint(AttributeConstraint.NONE) +// .build(); +// +// final ProductTypeDraft productTypeDraft = +// ProductTypeDraftBuilder.of( +// MAIN_PRODUCT_TYPE_KEY, +// MAIN_PRODUCT_TYPE_KEY, +// "a productType for t-shirts", +// emptyList()) +// .attributes(singletonList(setOfProductsAttributeDef)) +// .build(); +// +// final ProductType productType = +// sourceProjectClient +// .execute(ProductTypeCreateCommand.of(productTypeDraft)) +// .toCompletableFuture() +// .join(); +// +// final ConcurrentHashMap.KeySetView productIds = +// ConcurrentHashMap.newKeySet(); +// +// // create 500 products +// final CompletableFuture[] creationFutures = +// IntStream.range(0, 500) +// .mapToObj( +// index -> { +// final ProductVariantDraft masterVariant = +// ProductVariantDraftBuilder.of() +// .key(format("%d-mv-key", index)) +// .sku(format("%d-mv-sku", index)) +// .build(); +// +// final ProductDraft draft = +// ProductDraftBuilder.of( +// productType, +// ofEnglish(Integer.toString(index)), +// ofEnglish(format("%d-slug", index)), +// masterVariant) +// .key(format("%d-key", index)) +// .build(); +// return CTP_SOURCE_CLIENT +// .execute(ProductCreateCommand.of(draft)) +// .thenAccept(createdProduct -> productIds.add(createdProduct.getId())) +// .toCompletableFuture(); +// }) +// .toArray(CompletableFuture[]::new); +// +// CompletableFuture.allOf(creationFutures).join(); +// +// final ArrayNode setAttributeValue = JsonNodeFactory.instance.arrayNode(); +// final Set productReferences = +// productIds.stream() +// .map(productId -> createReferenceObject(Product.referenceTypeId(), productId)) +// .collect(Collectors.toSet()); +// setAttributeValue.addAll(productReferences); +// +// final ProductVariantDraft masterVariant = +// ProductVariantDraftBuilder.of() +// .key(MAIN_PRODUCT_MASTER_VARIANT_KEY) +// .sku(MAIN_PRODUCT_MASTER_VARIANT_KEY) +// .attributes(AttributeDraft.of(setOfProductsAttributeDef.getName(), setAttributeValue)) +// .build(); +// +// final ProductDraft draft = +// ProductDraftBuilder.of( +// productType, +// ofEnglish(MAIN_PRODUCT_KEY), +// ofEnglish(MAIN_PRODUCT_KEY), +// masterVariant) +// .key(MAIN_PRODUCT_KEY) +// .build(); +// +// sourceProjectClient.execute(ProductCreateCommand.of(draft)).toCompletableFuture().join(); +// } +// +// @AfterAll +// static void tearDownSuite() { +// cleanUpProjects(CTP_SOURCE_CLIENT, CTP_TARGET_CLIENT); +// } +// +// @Test +// void run_WithAProductWith500DistinctReferences_ShouldSyncCorrectly() { +// // test +// CliRunner.of() +// .run(new String[] {"-s", "all", "-r", "runnerName", "-f"}, createITSyncerFactory()); +// +// // assertions +// assertThat(cliRunnerTestLogger.getAllLoggingEvents()) +// .allMatch(loggingEvent -> !Level.ERROR.equals(loggingEvent.getLevel())); +// +// assertTypeSyncerLoggingEvents(typeSyncerTestLogger, 0); +// assertProductTypeSyncerLoggingEvents(productTypeSyncerTestLogger, 1); +// assertTaxCategorySyncerLoggingEvents(taxCategorySyncerTestLogger, 0); +// assertCategorySyncerLoggingEvents(categorySyncerTestLogger, 0); +// assertProductSyncerLoggingEvents(productSyncerTestLogger, 501); +// assertInventoryEntrySyncerLoggingEvents(inventoryEntrySyncerTestLogger, 0); +// assertCartDiscountSyncerLoggingEvents(cartDiscountSyncerTestLogger, 0); +// assertCustomerSyncerLoggingEvents(customerSyncerTestLogger, 0); +// assertShoppingListSyncerLoggingEvents(shoppingListSyncerTestLogger, 0); +// assertStateSyncerLoggingEvents( +// stateSyncerTestLogger, 1); // 1 state is built-in and it cant be deleted +// assertCustomObjectSyncerLoggingEvents(customObjectSyncerTestLogger, 0); +// +// assertAllResourcesAreSyncedToTarget(CTP_TARGET_CLIENT); +// } +// +// private static void assertAllResourcesAreSyncedToTarget( +// @Nonnull final SphereClient targetClient) { +// +// assertProductTypeExists(targetClient, MAIN_PRODUCT_TYPE_KEY); +// +// final List products = +// CtpQueryUtils.queryAll(targetClient, ProductQuery.of(), Function.identity()) +// .thenApply( +// fetchedProducts -> +// fetchedProducts.stream().flatMap(List::stream).collect(Collectors.toList())) +// .toCompletableFuture() +// .join(); +// assertThat(products).hasSize(501); +// +// final CustomObjectQuery customObjectQuery = +// CustomObjectQuery.of(WaitingToBeResolved.class) +// .byContainer("commercetools-sync-java.UnresolvedReferencesService.productDrafts"); +// +// final PagedQueryResult> queryResult = +// targetClient.execute(customObjectQuery).toCompletableFuture().join(); +// +// assertThat(queryResult.getResults()).isEmpty(); +// } +// } diff --git a/src/integration-test/java/com/commercetools/project/sync/util/IntegrationTestUtils.java b/src/integration-test/java/com/commercetools/project/sync/util/IntegrationTestUtils.java index 5dbbcf5e..62a69e2b 100644 --- a/src/integration-test/java/com/commercetools/project/sync/util/IntegrationTestUtils.java +++ b/src/integration-test/java/com/commercetools/project/sync/util/IntegrationTestUtils.java @@ -3,74 +3,35 @@ import static com.commercetools.project.sync.service.impl.CustomObjectServiceImpl.TIMESTAMP_GENERATOR_KEY; import static com.commercetools.project.sync.util.CtpClientUtils.CTP_SOURCE_CLIENT; import static com.commercetools.project.sync.util.CtpClientUtils.CTP_TARGET_CLIENT; -import static com.commercetools.project.sync.util.QueryUtils.queryAndExecute; import static java.lang.String.format; import static org.assertj.core.api.Assertions.assertThat; +import com.commercetools.api.client.ByProjectKeyCustomObjectsGet; +import com.commercetools.api.client.ProjectApiRoot; +import com.commercetools.api.client.QueryUtils; +import com.commercetools.api.models.category.Category; +import com.commercetools.api.models.category.CategoryPagedQueryResponse; +import com.commercetools.api.models.customer.Customer; +import com.commercetools.api.models.customer.CustomerPagedQueryResponse; +import com.commercetools.api.models.product.Product; +import com.commercetools.api.models.product.ProductPagedQueryResponse; +import com.commercetools.api.models.product.ProductUnpublishActionBuilder; +import com.commercetools.api.models.product.ProductVariant; +import com.commercetools.api.models.product_type.ProductType; +import com.commercetools.api.models.product_type.ProductTypePagedQueryResponse; +import com.commercetools.api.models.product_type.ProductTypeRemoveAttributeDefinitionActionBuilder; +import com.commercetools.api.models.state.State; +import com.commercetools.api.models.state.StatePagedQueryResponse; import com.commercetools.project.sync.SyncerFactory; -import com.commercetools.project.sync.model.response.LastSyncCustomObject; -import com.commercetools.sync.commons.utils.CtpQueryUtils; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.JsonNodeFactory; import com.fasterxml.jackson.databind.node.ObjectNode; -import io.sphere.sdk.cartdiscounts.commands.CartDiscountDeleteCommand; -import io.sphere.sdk.cartdiscounts.queries.CartDiscountQuery; -import io.sphere.sdk.categories.Category; -import io.sphere.sdk.categories.commands.CategoryDeleteCommand; -import io.sphere.sdk.categories.queries.CategoryQuery; -import io.sphere.sdk.channels.commands.ChannelDeleteCommand; -import io.sphere.sdk.channels.queries.ChannelQuery; -import io.sphere.sdk.client.ConcurrentModificationException; -import io.sphere.sdk.client.SphereClient; -import io.sphere.sdk.client.SphereRequest; -import io.sphere.sdk.commands.UpdateAction; -import io.sphere.sdk.customergroups.commands.CustomerGroupDeleteCommand; -import io.sphere.sdk.customergroups.queries.CustomerGroupQuery; -import io.sphere.sdk.customers.Customer; -import io.sphere.sdk.customers.commands.CustomerDeleteCommand; -import io.sphere.sdk.customers.queries.CustomerQuery; -import io.sphere.sdk.customobjects.CustomObject; -import io.sphere.sdk.customobjects.commands.CustomObjectDeleteCommand; -import io.sphere.sdk.customobjects.queries.CustomObjectQuery; -import io.sphere.sdk.inventory.commands.InventoryEntryDeleteCommand; -import io.sphere.sdk.inventory.queries.InventoryEntryQuery; -import io.sphere.sdk.models.Versioned; -import io.sphere.sdk.productdiscounts.commands.ProductDiscountDeleteCommand; -import io.sphere.sdk.productdiscounts.queries.ProductDiscountQuery; -import io.sphere.sdk.products.Product; -import io.sphere.sdk.products.ProductVariant; -import io.sphere.sdk.products.commands.ProductDeleteCommand; -import io.sphere.sdk.products.commands.ProductUpdateCommand; -import io.sphere.sdk.products.commands.updateactions.Unpublish; -import io.sphere.sdk.products.queries.ProductQuery; -import io.sphere.sdk.producttypes.ProductType; -import io.sphere.sdk.producttypes.commands.ProductTypeDeleteCommand; -import io.sphere.sdk.producttypes.commands.ProductTypeUpdateCommand; -import io.sphere.sdk.producttypes.commands.updateactions.RemoveAttributeDefinition; -import io.sphere.sdk.producttypes.queries.ProductTypeQuery; -import io.sphere.sdk.queries.PagedQueryResult; -import io.sphere.sdk.queries.QueryPredicate; -import io.sphere.sdk.shippingmethods.commands.ShippingMethodDeleteCommand; -import io.sphere.sdk.shippingmethods.queries.ShippingMethodQuery; -import io.sphere.sdk.shoppinglists.commands.ShoppingListDeleteCommand; -import io.sphere.sdk.shoppinglists.queries.ShoppingListQuery; -import io.sphere.sdk.states.State; -import io.sphere.sdk.states.commands.StateDeleteCommand; -import io.sphere.sdk.states.queries.StateQuery; -import io.sphere.sdk.taxcategories.commands.TaxCategoryDeleteCommand; -import io.sphere.sdk.taxcategories.queries.TaxCategoryQuery; -import io.sphere.sdk.types.commands.TypeDeleteCommand; -import io.sphere.sdk.types.queries.TypeQuery; +import io.vrap.rmf.base.client.ApiHttpResponse; import java.time.Clock; import java.util.ArrayList; import java.util.List; -import java.util.Map; -import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; -import java.util.concurrent.ConcurrentHashMap; -import java.util.function.Consumer; -import java.util.stream.Collectors; import javax.annotation.Nonnull; public final class IntegrationTestUtils { @@ -88,55 +49,59 @@ public static SyncerFactory createITSyncerFactory() { * @param ctpClient the client to delete the custom objects from. */ public static void deleteLastSyncCustomObjects( - @Nonnull final SphereClient ctpClient, @Nonnull final String sourceProjectKey) { + @Nonnull final ProjectApiRoot ctpClient, @Nonnull final String sourceProjectKey) { // 1. First query for the time generator custom object - final QueryPredicate> timeGeneratorPredicate = - QueryPredicate.of(format("key=\"%s\"", TIMESTAMP_GENERATOR_KEY)); - - final CustomObjectQuery timeGeneratorCustomObjectQuery = - CustomObjectQuery.of(String.class).plusPredicates(timeGeneratorPredicate); + final ByProjectKeyCustomObjectsGet timeGeneratorCustomObjectQuery = + ctpClient.customObjects().get().withWhere(format("key=\"%s\"", TIMESTAMP_GENERATOR_KEY)); final List deletionStages = new ArrayList<>(); final CompletableFuture timeGeneratorDeletionsStage = - ctpClient - .execute(timeGeneratorCustomObjectQuery) - .thenApply(PagedQueryResult::getResults) + timeGeneratorCustomObjectQuery + .execute() + .thenApply( + customObjectPagedQueryResponseApiHttpResponse -> + customObjectPagedQueryResponseApiHttpResponse.getBody().getResults()) .thenCompose( customObjects -> CompletableFuture.allOf( customObjects.stream() .map( customObject -> - ctpClient.execute( - CustomObjectDeleteCommand.of(customObject, String.class))) - .map(CompletionStage::toCompletableFuture) + ctpClient + .customObjects() + .withContainerAndKey( + customObject.getContainer(), customObject.getKey()) + .delete() + .execute()) .toArray(CompletableFuture[]::new))) .toCompletableFuture(); deletionStages.add(timeGeneratorDeletionsStage); // 2. Then query for the lastSync custom objects - final QueryPredicate> lastSyncPredicate = - QueryPredicate.of(format("key=\"%s\"", sourceProjectKey)); - - final CustomObjectQuery lastSyncCustomObjectQuery = - CustomObjectQuery.of(LastSyncCustomObject.class).plusPredicates(lastSyncPredicate); + final ByProjectKeyCustomObjectsGet lastSyncCustomObjectQuery = + ctpClient.customObjects().get().withWhere(format("key=\"%s\"", sourceProjectKey)); final CompletableFuture lastSyncCustomObjectDeletionFutures = - ctpClient - .execute(lastSyncCustomObjectQuery) - .thenApply(PagedQueryResult::getResults) + lastSyncCustomObjectQuery + .execute() + .thenApply( + customObjectPagedQueryResponseApiHttpResponse -> + customObjectPagedQueryResponseApiHttpResponse.getBody().getResults()) .thenCompose( customObjects -> CompletableFuture.allOf( customObjects.stream() .map( customObject -> - ctpClient.execute( - CustomObjectDeleteCommand.of( - customObject, LastSyncCustomObject.class))) + ctpClient + .customObjects() + .withContainerAndKey( + customObject.getContainer(), customObject.getKey()) + .delete() + .execute()) .map(CompletionStage::toCompletableFuture) .toArray(CompletableFuture[]::new))) .toCompletableFuture(); @@ -148,32 +113,150 @@ public static void deleteLastSyncCustomObjects( } public static void cleanUpProjects( - @Nonnull final SphereClient sourceClient, @Nonnull final SphereClient targetClient) { - + @Nonnull final ProjectApiRoot sourceClient, @Nonnull final ProjectApiRoot targetClient) { deleteProjectData(sourceClient); deleteProjectData(targetClient); - deleteLastSyncCustomObjects(targetClient, sourceClient.getConfig().getProjectKey()); + deleteLastSyncCustomObjects(targetClient, sourceClient.getProjectKey()); } - private static void deleteProjectData(@Nonnull final SphereClient client) { - queryAndExecute(client, CategoryQuery.of(), CategoryDeleteCommand::of).join(); - queryAndExecute( - client, - ProductQuery.of(), - versioned -> ProductUpdateCommand.of(versioned, Unpublish.of())) + private static void deleteProjectData(@Nonnull final ProjectApiRoot client) { + QueryUtils.queryAll( + client.categories().get(), + categories -> { + CompletableFuture.allOf( + categories.stream() + .map( + category -> + client + .categories() + .delete(category) + .execute() + .thenApply(ApiHttpResponse::getBody)) + .map(CompletionStage::toCompletableFuture) + .toArray(CompletableFuture[]::new)) + .join(); + }) + .toCompletableFuture() + .join(); + QueryUtils.queryAll( + client.products().get(), + products -> { + CompletableFuture.allOf( + products.stream() + .map( + product -> + client + .products() + .update(product) + .with( + actionBuilder -> + actionBuilder.plus( + ProductUnpublishActionBuilder.of())) + .execute() + .thenApply(ApiHttpResponse::getBody)) + .map(CompletionStage::toCompletableFuture) + .toArray(CompletableFuture[]::new)) + .join(); + }) + .toCompletableFuture() .join(); final CompletableFuture deleteProduct = - queryAndExecute(client, ProductQuery.of(), ProductDeleteCommand::of); + QueryUtils.queryAll( + client.products().get(), + products -> { + CompletableFuture.allOf( + products.stream() + .map( + product -> + client + .products() + .delete(product) + .execute() + .thenApply(ApiHttpResponse::getBody)) + .map(CompletionStage::toCompletableFuture) + .toArray(CompletableFuture[]::new)) + .join(); + }) + .toCompletableFuture(); + final CompletableFuture deleteInventory = - queryAndExecute(client, InventoryEntryQuery.of(), InventoryEntryDeleteCommand::of); + QueryUtils.queryAll( + client.inventory().get(), + inventoryEntries -> { + CompletableFuture.allOf( + inventoryEntries.stream() + .map( + inventoryEntry -> + client + .inventory() + .delete(inventoryEntry) + .execute() + .thenApply(ApiHttpResponse::getBody)) + .map(CompletionStage::toCompletableFuture) + .toArray(CompletableFuture[]::new)) + .join(); + }) + .toCompletableFuture(); + final CompletableFuture deleteCartDiscount = - queryAndExecute(client, CartDiscountQuery.of(), CartDiscountDeleteCommand::of); + QueryUtils.queryAll( + client.cartDiscounts().get(), + cartDiscounts -> { + CompletableFuture.allOf( + cartDiscounts.stream() + .map( + cartDiscount -> + client + .cartDiscounts() + .delete(cartDiscount) + .execute() + .thenApply(ApiHttpResponse::getBody)) + .map(CompletionStage::toCompletableFuture) + .toArray(CompletableFuture[]::new)) + .join(); + }) + .toCompletableFuture(); + final CompletableFuture deleteCustomObject = - queryAndExecute( - client, CustomObjectQuery.ofJsonNode(), CustomObjectDeleteCommand::ofJsonNode); + QueryUtils.queryAll( + client.customObjects().get(), + customObjects -> { + CompletableFuture.allOf( + customObjects.stream() + .map( + customObject -> + client + .customObjects() + .withContainerAndKey( + customObject.getContainer(), customObject.getKey()) + .delete() + .execute() + .thenApply(ApiHttpResponse::getBody)) + .map(CompletionStage::toCompletableFuture) + .toArray(CompletableFuture[]::new)) + .join(); + }) + .toCompletableFuture(); + final CompletableFuture deleteProductDiscount = - queryAndExecute(client, ProductDiscountQuery.of(), ProductDiscountDeleteCommand::of); + QueryUtils.queryAll( + client.productDiscounts().get(), + productDiscounts -> { + CompletableFuture.allOf( + productDiscounts.stream() + .map( + productDiscount -> + client + .productDiscounts() + .delete(productDiscount) + .execute() + .thenApply(ApiHttpResponse::getBody)) + .map(CompletionStage::toCompletableFuture) + .toArray(CompletableFuture[]::new)) + .join(); + }) + .toCompletableFuture(); CompletableFuture.allOf( deleteProduct, @@ -183,27 +266,157 @@ private static void deleteProjectData(@Nonnull final SphereClient client) { deleteProductDiscount) .join(); - queryAndExecute( - client, - // builtIn is excluded as it cannot be deleted - StateQuery.of().plusPredicates(QueryPredicate.of("builtIn=\"false\"")), - StateDeleteCommand::of) + QueryUtils.queryAll( + client.states().get().withWhere("builtIn=\"false\""), + states -> { + CompletableFuture.allOf( + states.stream() + .map( + state -> + client + .states() + .delete(state) + .execute() + .thenApply(ApiHttpResponse::getBody)) + .map(CompletionStage::toCompletableFuture) + .toArray(CompletableFuture[]::new)) + .join(); + }) + .toCompletableFuture() .join(); - queryAndExecute(client, ShoppingListQuery.of(), ShoppingListDeleteCommand::of).join(); + QueryUtils.queryAll( + client.shoppingLists().get(), + shoppingLists -> { + CompletableFuture.allOf( + shoppingLists.stream() + .map( + shoppingList -> + client + .shoppingLists() + .delete(shoppingList) + .execute() + .thenApply(ApiHttpResponse::getBody)) + .map(CompletionStage::toCompletableFuture) + .toArray(CompletableFuture[]::new)) + .join(); + }) + .toCompletableFuture() + .join(); final CompletableFuture deleteType = - queryAndExecute(client, TypeQuery.of(), TypeDeleteCommand::of); + QueryUtils.queryAll( + client.types().get(), + types -> { + CompletableFuture.allOf( + types.stream() + .map( + type -> + client + .types() + .delete(type) + .execute() + .thenApply(ApiHttpResponse::getBody)) + .map(CompletionStage::toCompletableFuture) + .toArray(CompletableFuture[]::new)) + .join(); + }) + .toCompletableFuture(); + final CompletableFuture deleteShippingMethod = - queryAndExecute(client, ShippingMethodQuery.of(), ShippingMethodDeleteCommand::of); + QueryUtils.queryAll( + client.shippingMethods().get(), + shippingMethods -> { + CompletableFuture.allOf( + shippingMethods.stream() + .map( + shippingMethod -> + client + .shippingMethods() + .delete(shippingMethod) + .execute() + .thenApply(ApiHttpResponse::getBody)) + .map(CompletionStage::toCompletableFuture) + .toArray(CompletableFuture[]::new)) + .join(); + }) + .toCompletableFuture(); + final CompletableFuture deleteTaxCategory = - queryAndExecute(client, TaxCategoryQuery.of(), TaxCategoryDeleteCommand::of); + QueryUtils.queryAll( + client.taxCategories().get(), + taxCategories -> { + CompletableFuture.allOf( + taxCategories.stream() + .map( + taxCategory -> + client + .taxCategories() + .delete(taxCategory) + .execute() + .thenApply(ApiHttpResponse::getBody)) + .map(CompletionStage::toCompletableFuture) + .toArray(CompletableFuture[]::new)) + .join(); + }) + .toCompletableFuture(); + final CompletableFuture deleteCustomer = - queryAndExecute(client, CustomerQuery.of(), CustomerDeleteCommand::of); + QueryUtils.queryAll( + client.customers().get(), + customers -> { + CompletableFuture.allOf( + customers.stream() + .map( + customer -> + client + .customers() + .delete(customer) + .execute() + .thenApply(ApiHttpResponse::getBody)) + .map(CompletionStage::toCompletableFuture) + .toArray(CompletableFuture[]::new)) + .join(); + }) + .toCompletableFuture(); + final CompletableFuture deleteCustomerGroup = - queryAndExecute(client, CustomerGroupQuery.of(), CustomerGroupDeleteCommand::of); + QueryUtils.queryAll( + client.customerGroups().get(), + customerGroups -> { + CompletableFuture.allOf( + customerGroups.stream() + .map( + customerGroup -> + client + .customerGroups() + .delete(customerGroup) + .execute() + .thenApply(ApiHttpResponse::getBody)) + .map(CompletionStage::toCompletableFuture) + .toArray(CompletableFuture[]::new)) + .join(); + }) + .toCompletableFuture(); + final CompletableFuture deleteChannel = - queryAndExecute(client, ChannelQuery.of(), ChannelDeleteCommand::of); + QueryUtils.queryAll( + client.channels().get(), + channels -> { + CompletableFuture.allOf( + channels.stream() + .map( + channel -> + client + .channels() + .delete(channel) + .execute() + .thenApply(ApiHttpResponse::getBody)) + .map(CompletionStage::toCompletableFuture) + .toArray(CompletableFuture[]::new)) + .join(); + }) + .toCompletableFuture(); CompletableFuture.allOf( deleteType, @@ -216,173 +429,169 @@ private static void deleteProjectData(@Nonnull final SphereClient client) { deleteProductTypes(client); } - private static void deleteProductTypes(@Nonnull final SphereClient ctpClient) { + private static void deleteProductTypes(@Nonnull final ProjectApiRoot ctpClient) { deleteProductTypeAttributes(ctpClient); deleteProductTypesWithRetry(ctpClient); } - private static void deleteProductTypesWithRetry(@Nonnull final SphereClient ctpClient) { - final Consumer> pageConsumer = - pageElements -> - CompletableFuture.allOf( - pageElements.stream() - .map(productType -> deleteProductTypeWithRetry(ctpClient, productType)) - .map(CompletionStage::toCompletableFuture) - .toArray(CompletableFuture[]::new)) - .join(); - - CtpQueryUtils.queryAll(ctpClient, ProductTypeQuery.of(), pageConsumer) + private static void deleteProductTypesWithRetry(@Nonnull final ProjectApiRoot ctpClient) { + // todo: add retry + QueryUtils.queryAll( + ctpClient.productTypes().get(), + productTypes -> { + CompletableFuture.allOf( + productTypes.stream() + .map( + productType -> + ctpClient + .productTypes() + .delete(productType) + .execute() + .thenApply(ApiHttpResponse::getBody)) + .map(CompletionStage::toCompletableFuture) + .toArray(CompletableFuture[]::new)) + .join(); + }) .toCompletableFuture() .join(); } - private static CompletionStage deleteProductTypeWithRetry( - @Nonnull final SphereClient ctpClient, @Nonnull final ProductType productType) { - return ctpClient - .execute(ProductTypeDeleteCommand.of(productType)) - .handle( - (result, throwable) -> { - if (throwable instanceof ConcurrentModificationException) { - Long currentVersion = - ((ConcurrentModificationException) throwable).getCurrentVersion(); - SphereRequest retry = - ProductTypeDeleteCommand.of(Versioned.of(productType.getId(), currentVersion)); - ctpClient.execute(retry); - } - return result; - }); - } - - private static void deleteProductTypeAttributes(@Nonnull final SphereClient ctpClient) { - final ConcurrentHashMap>> productTypesToUpdate = - new ConcurrentHashMap<>(); - - CtpQueryUtils.queryAll( - ctpClient, - ProductTypeQuery.of(), - page -> { - page.forEach( - productType -> { - final Set> removeActions = - productType.getAttributes().stream() - .map( - attributeDefinition -> - RemoveAttributeDefinition.of(attributeDefinition.getName())) - .collect(Collectors.toSet()); - productTypesToUpdate.put(productType, removeActions); - }); + private static void deleteProductTypeAttributes(@Nonnull final ProjectApiRoot ctpClient) { + QueryUtils.queryAll( + ctpClient.productTypes().get(), + productTypes -> { + CompletableFuture.allOf( + productTypes.stream() + .map( + productType -> + ctpClient + .productTypes() + .update(productType) + .with( + builder -> { + productType + .getAttributes() + .forEach( + attributeDefinition -> + builder.plus( + ProductTypeRemoveAttributeDefinitionActionBuilder + .of() + .name( + attributeDefinition + .getName()))); + return builder; + }) + .execute() + .thenApply(ApiHttpResponse::getBody)) + .map(CompletionStage::toCompletableFuture) + .toArray(CompletableFuture[]::new)) + .join(); }) - .thenCompose( - aVoid -> - CompletableFuture.allOf( - productTypesToUpdate.entrySet().stream() - .map(entry -> updateProductTypeWithRetry(ctpClient, entry)) - .toArray(CompletableFuture[]::new))) .toCompletableFuture() .join(); } - private static CompletionStage updateProductTypeWithRetry( - @Nonnull final SphereClient ctpClient, - @Nonnull final Map.Entry>> entry) { - return ctpClient - .execute(ProductTypeUpdateCommand.of(entry.getKey(), new ArrayList<>(entry.getValue()))) - .handle( - (result, throwable) -> { - if (throwable instanceof ConcurrentModificationException) { - Long currentVersion = - ((ConcurrentModificationException) throwable).getCurrentVersion(); - SphereRequest retry = - ProductTypeUpdateCommand.of( - Versioned.of(entry.getKey().getId(), currentVersion), - new ArrayList<>(entry.getValue())); - ctpClient.execute(retry); - } - return result; - }); - } - @Nonnull public static ProductType assertProductTypeExists( - @Nonnull final SphereClient ctpClient, @Nonnull final String productTypeKey) { - final PagedQueryResult productTypeQueryResult = - ctpClient.execute(ProductTypeQuery.of().byKey(productTypeKey)).toCompletableFuture().join(); + @Nonnull final ProjectApiRoot ctpClient, @Nonnull final String key) { + final ProductTypePagedQueryResponse productTypePagedQueryResponse = + ctpClient + .productTypes() + .get() + .withWhere("key=:key") + .withPredicateVar("key", key) + .execute() + .thenApply(ApiHttpResponse::getBody) + .join(); - assertThat(productTypeQueryResult.getResults()) + assertThat(productTypePagedQueryResponse.getResults()) .hasSize(1) .singleElement() - .satisfies(productType -> assertThat(productType.getKey()).isEqualTo(productTypeKey)); + .satisfies(productType -> assertThat(productType.getKey()).isEqualTo(key)); - return productTypeQueryResult.getResults().get(0); + return productTypePagedQueryResponse.getResults().get(0); } @Nonnull public static Category assertCategoryExists( - @Nonnull final SphereClient ctpClient, @Nonnull final String key) { - final String queryPredicate = format("key=\"%s\"", key); - - final PagedQueryResult categoryQueryResult = + @Nonnull final ProjectApiRoot ctpClient, @Nonnull final String key) { + final CategoryPagedQueryResponse categoryPagedQueryResponse = ctpClient - .execute(CategoryQuery.of().withPredicates(QueryPredicate.of(queryPredicate))) - .toCompletableFuture() + .categories() + .get() + .withWhere("key=:key") + .withPredicateVar("key", key) + .execute() + .thenApply(ApiHttpResponse::getBody) .join(); - assertThat(categoryQueryResult.getResults()) + assertThat(categoryPagedQueryResponse.getResults()) .hasSize(1) .singleElement() .satisfies(category -> assertThat(category.getKey()).isEqualTo(key)); - return categoryQueryResult.getResults().get(0); + return categoryPagedQueryResponse.getResults().get(0); } @Nonnull public static State assertStateExists( - @Nonnull final SphereClient ctpClient, @Nonnull final String key) { - final String queryPredicate = format("key=\"%s\"", key); - - final PagedQueryResult stateQueryResult = + @Nonnull final ProjectApiRoot ctpClient, @Nonnull final String key) { + final StatePagedQueryResponse statePagedQueryResponse = ctpClient - .execute(StateQuery.of().withPredicates(QueryPredicate.of(queryPredicate))) - .toCompletableFuture() + .states() + .get() + .withWhere("key=:key") + .withPredicateVar("key", key) + .execute() + .thenApply(ApiHttpResponse::getBody) .join(); - assertThat(stateQueryResult.getResults()) + assertThat(statePagedQueryResponse.getResults()) .hasSize(1) .singleElement() .satisfies(state -> assertThat(state.getKey()).isEqualTo(key)); - return stateQueryResult.getResults().get(0); + return statePagedQueryResponse.getResults().get(0); } @Nonnull public static Customer assertCustomerExists( - @Nonnull final SphereClient ctpClient, @Nonnull final String key) { - final String queryPredicate = format("key=\"%s\"", key); - - final PagedQueryResult customerQueryResult = + @Nonnull final ProjectApiRoot ctpClient, @Nonnull final String key) { + final CustomerPagedQueryResponse customerPagedQueryResponse = ctpClient - .execute(CustomerQuery.of().withPredicates(QueryPredicate.of(queryPredicate))) - .toCompletableFuture() + .customers() + .get() + .withWhere("key=:key") + .withPredicateVar("key", key) + .execute() + .thenApply(ApiHttpResponse::getBody) .join(); - assertThat(customerQueryResult.getResults()) + assertThat(customerPagedQueryResponse.getResults()) .hasSize(1) .singleElement() .satisfies(customer -> assertThat(customer.getKey()).isEqualTo(key)); - return customerQueryResult.getResults().get(0); + return customerPagedQueryResponse.getResults().get(0); } @Nonnull public static Product assertProductExists( - @Nonnull final SphereClient targetClient, + @Nonnull final ProjectApiRoot ctpClient, @Nonnull final String productKey, @Nonnull final String masterVariantKey, @Nonnull final String masterVariantSku) { - final PagedQueryResult productQueryResult = - targetClient.execute(ProductQuery.of()).toCompletableFuture().join(); + final ProductPagedQueryResponse productPagedQueryResponse = + ctpClient + .products() + .get() + .withWhere("key=:key") + .withPredicateVar("key", productKey) + .execute() + .thenApply(ApiHttpResponse::getBody) + .join(); - assertThat(productQueryResult.getResults()) + assertThat(productPagedQueryResponse.getResults()) .hasSize(1) .singleElement() .satisfies( @@ -394,7 +603,7 @@ public static Product assertProductExists( assertThat(stagedMasterVariant.getSku()).isEqualTo(masterVariantSku); }); - return productQueryResult.getResults().get(0); + return productPagedQueryResponse.getResults().get(0); } @Nonnull diff --git a/src/integration-test/java/com/commercetools/project/sync/util/QueryUtils.java b/src/integration-test/java/com/commercetools/project/sync/util/QueryUtils.java index 7dacf2b5..5947b90b 100644 --- a/src/integration-test/java/com/commercetools/project/sync/util/QueryUtils.java +++ b/src/integration-test/java/com/commercetools/project/sync/util/QueryUtils.java @@ -1,67 +1,68 @@ -package com.commercetools.project.sync.util; - -import com.commercetools.sync.commons.utils.CtpQueryUtils; -import io.sphere.sdk.client.SphereClient; -import io.sphere.sdk.client.SphereRequest; -import io.sphere.sdk.models.ResourceView; -import io.sphere.sdk.queries.QueryDsl; -import java.util.List; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionStage; -import java.util.function.Consumer; -import java.util.function.Function; -import javax.annotation.Nonnull; - -public final class QueryUtils { - /** - * Applies the {@code resourceToRequestMapper} function on each page, resulting from the {@code - * query} executed by the {@code ctpClient}, to map each resource to a {@link SphereRequest} and - * then executes these requests in parallel within each page. - * - * @param ctpClient defines the CTP project to apply the query on. - * @param query query that should be made on the CTP project. - * @param resourceToRequestMapper defines a mapper function that should be applied on each - * resource, in the fetched page from the query on the specified CTP project, to map it to a - * {@link SphereRequest}. - */ - public static > - CompletableFuture queryAndExecute( - @Nonnull final SphereClient ctpClient, - @Nonnull final QueryDsl query, - @Nonnull final Function> resourceToRequestMapper) { - - return queryAndCompose( - ctpClient, query, resource -> ctpClient.execute(resourceToRequestMapper.apply(resource))); - } - - /** - * Applies the {@code resourceToStageMapper} function on each page, resulting from the {@code - * query} executed by the {@code ctpClient}, to map each resource to a {@link CompletionStage} and - * then executes these stages in parallel within each page. - * - * @param ctpClient defines the CTP project to apply the query on. - * @param query query that should be made on the CTP project. - * @param resourceToStageMapper defines a mapper function that should be applied on each resource, - * in the fetched page from the query on the specified CTP project, to map it to a {@link - * CompletionStage} which will be executed (in a blocking fashion) after every page fetch. - */ - private static , S> - CompletableFuture queryAndCompose( - @Nonnull final SphereClient ctpClient, - @Nonnull final QueryDsl query, - @Nonnull final Function> resourceToStageMapper) { - - final Consumer> pageConsumer = - pageElements -> - CompletableFuture.allOf( - pageElements.stream() - .map(resourceToStageMapper) - .map(CompletionStage::toCompletableFuture) - .toArray(CompletableFuture[]::new)) - .join(); - - return CtpQueryUtils.queryAll(ctpClient, query, pageConsumer).toCompletableFuture(); - } - - private QueryUtils() {} -} +// package com.commercetools.project.sync.util; +// +// import com.commercetools.api.client.ProjectApiRoot; +// import com.commercetools.api.models.common.BaseResource; +// +// import java.util.List; +// import java.util.concurrent.CompletableFuture; +// import java.util.concurrent.CompletionStage; +// import java.util.function.Consumer; +// import java.util.function.Function; +// import javax.annotation.Nonnull; +// +// public final class QueryUtils { +// /** +// * Applies the {@code resourceToRequestMapper} function on each page, resulting from the {@code +// * query} executed by the {@code ctpClient}, to map each resource to a {@link SphereRequest} and +// * then executes these requests in parallel within each page. +// * +// * @param ctpClient defines the CTP project to apply the query on. +// * @param query query that should be made on the CTP project. +// * @param resourceToRequestMapper defines a mapper function that should be applied on each +// * resource, in the fetched page from the query on the specified CTP project, to map it to a +// * {@link SphereRequest}. +// */ +// public static > +// CompletableFuture queryAndExecute( +// @Nonnull final ProjectApiRoot ctpClient, +// @Nonnull final QueryDsl query, +// @Nonnull final Function resourceToRequestMapper) { +// +// return queryAndCompose( +// ctpClient, query, resource -> ctpClient.execute(resourceToRequestMapper.apply(resource))); +// } +// +// /** +// * Applies the {@code resourceToStageMapper} function on each page, resulting from the {@code +// * query} executed by the {@code ctpClient}, to map each resource to a {@link CompletionStage} +// and +// * then executes these stages in parallel within each page. +// * +// * @param ctpClient defines the CTP project to apply the query on. +// * @param query query that should be made on the CTP project. +// * @param resourceToStageMapper defines a mapper function that should be applied on each +// resource, +// * in the fetched page from the query on the specified CTP project, to map it to a {@link +// * CompletionStage} which will be executed (in a blocking fashion) after every page fetch. +// */ +// private static , S> +// CompletableFuture queryAndCompose( +// @Nonnull final ProjectApiRoot ctpClient, +// @Nonnull final QueryDsl query, +// @Nonnull final Function> resourceToStageMapper) { +// +// final Consumer> pageConsumer = +// pageElements -> +// CompletableFuture.allOf( +// pageElements.stream() +// .map(resourceToStageMapper) +// .map(CompletionStage::toCompletableFuture) +// .toArray(CompletableFuture[]::new)) +// .join(); +// +// return com.commercetools.api.client.QueryUtils.queryAll(ctpClient, query, +// pageConsumer).toCompletableFuture(); +// } +// +// private QueryUtils() {} +// } diff --git a/src/main/java/com/commercetools/project/sync/category/CategorySyncer.java b/src/main/java/com/commercetools/project/sync/category/CategorySyncer.java index a0f929bb..6fb23e19 100644 --- a/src/main/java/com/commercetools/project/sync/category/CategorySyncer.java +++ b/src/main/java/com/commercetools/project/sync/category/CategorySyncer.java @@ -28,8 +28,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -// This class compiles but not tested yet -// TODO: Test class and adjust logic if needed public final class CategorySyncer extends Syncer< Category, diff --git a/src/main/java/com/commercetools/project/sync/util/CtpClientUtils.java b/src/main/java/com/commercetools/project/sync/util/CtpClientUtils.java index d304e6c9..265a2d68 100644 --- a/src/main/java/com/commercetools/project/sync/util/CtpClientUtils.java +++ b/src/main/java/com/commercetools/project/sync/util/CtpClientUtils.java @@ -43,7 +43,8 @@ private static ProjectApiRoot getCtpClient(@Nonnull final String propertiesPrefi properties = loadFromEnvVars(propertiesPrefix); } if (properties.isEmpty()) { - throw new InvalidPropertiesFormatException("Please provide CTP credentials for running project sync."); + throw new InvalidPropertiesFormatException( + "Please provide CTP credentials for running project sync."); } final String projectKey = @@ -52,7 +53,7 @@ private static ProjectApiRoot getCtpClient(@Nonnull final String propertiesPrefi extract(properties, propertiesPrefix, PROPERTIES_KEY_CLIENT_ID_SUFFIX); final String clientSecret = extract(properties, propertiesPrefix, PROPERTIES_KEY_CLIENT_SECRET_SUFFIX); - final String apiUrl = + final String apiUrl = extract( properties, propertiesPrefix, diff --git a/src/test/java/com/commercetools/project/sync/category/CategorySyncerTest.java b/src/test/java/com/commercetools/project/sync/category/CategorySyncerTest.java index b62506b8..a18d531f 100644 --- a/src/test/java/com/commercetools/project/sync/category/CategorySyncerTest.java +++ b/src/test/java/com/commercetools/project/sync/category/CategorySyncerTest.java @@ -1,13 +1,44 @@ package com.commercetools.project.sync.category; +import static com.commercetools.project.sync.util.TestUtils.*; +import static com.commercetools.sync.categories.utils.CategoryTransformUtils.toCategoryDrafts; +import static java.lang.String.format; +import static java.util.Arrays.asList; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import com.commercetools.api.client.ByProjectKeyCategoriesGet; +import com.commercetools.api.client.ByProjectKeyCategoriesKeyByKeyGet; +import com.commercetools.api.client.ByProjectKeyCategoriesKeyByKeyRequestBuilder; +import com.commercetools.api.client.ByProjectKeyCategoriesRequestBuilder; +import com.commercetools.api.client.ByProjectKeyGraphqlPost; +import com.commercetools.api.client.ByProjectKeyGraphqlRequestBuilder; +import com.commercetools.api.client.ProjectApiRoot; +import com.commercetools.api.models.category.Category; +import com.commercetools.api.models.category.CategoryDraft; +import com.commercetools.api.models.category.CategoryPagedQueryResponse; +import com.commercetools.api.models.category.CategoryPagedQueryResponseBuilder; +import com.commercetools.api.models.graph_ql.GraphQLRequest; +import com.commercetools.api.models.graph_ql.GraphQLResponse; +import com.commercetools.sync.categories.CategorySync; import com.commercetools.sync.commons.utils.CaffeineReferenceIdToKeyCacheImpl; import com.commercetools.sync.commons.utils.ReferenceIdToKeyCache; +import com.fasterxml.jackson.core.JsonProcessingException; +import io.vrap.rmf.base.client.ApiHttpResponse; +import java.time.Clock; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionStage; +import java.util.stream.Collectors; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import uk.org.lidalia.slf4jtest.LoggingEvent; import uk.org.lidalia.slf4jtest.TestLogger; import uk.org.lidalia.slf4jtest.TestLoggerFactory; -// These tests aren't migrated -// TODO: Migrate tests class CategorySyncerTest { private final TestLogger syncerTestLogger = TestLoggerFactory.getTestLogger(CategorySyncer.class); @@ -19,156 +50,215 @@ void setup() { syncerTestLogger.clearAll(); } - // @Test - // void of_ShouldCreateCategorySyncerInstance() { - // // test - // final CategorySyncer categorySyncer = - // CategorySyncer.of(mock(SphereClient.class), mock(SphereClient.class), getMockedClock()); - // - // // assertions - // CategoryQuery expectedQuery = CategoryQuery.of(); - // assertThat(categorySyncer).isNotNull(); - // assertThat(categorySyncer.getQuery()).isEqualTo(expectedQuery); - // assertThat(categorySyncer.getSync()).isExactlyInstanceOf(CategorySync.class); - // } - // - // @Test - // void transform_ShouldReplaceCategoryReferenceIdsWithKeys() { - // // preparation - // final SphereClient sourceClient = mock(SphereClient.class); - // final CategorySyncer categorySyncer = - // CategorySyncer.of(sourceClient, mock(SphereClient.class), getMockedClock()); - // final List categoryPage = - // asList( - // readObjectFromResource("category-key-1.json", Category.class), - // readObjectFromResource("category-key-2.json", Category.class)); - // final List referenceIds = - // categoryPage.stream() - // .filter(category -> category.getCustom() != null) - // .map(category -> category.getCustom().getType().getId()) - // .collect(Collectors.toList()); - // - // final String jsonStringCustomTypes = - // "{\"results\":[{\"id\":\"53c4a8b4-754f-4b95-b6f2-3e1e70e3d0c3\"," + "\"key\":\"cat1\"} - // ]}"; - // final ResourceKeyIdGraphQlResult customTypesResult = - // SphereJsonUtils.readObject(jsonStringCustomTypes, ResourceKeyIdGraphQlResult.class); - // - // when(sourceClient.execute(any(ResourceIdsGraphQlRequest.class))) - // .thenReturn(CompletableFuture.completedFuture(customTypesResult)); - // - // // test - // final CompletionStage> draftsFromPageStage = - // categorySyncer.transform(categoryPage); - // - // // assertions - // final List expectedResult = - // toCategoryDrafts(sourceClient, referenceIdToKeyCache, categoryPage).join(); - // final List referenceKeys = - // expectedResult.stream() - // .filter(category -> category.getCustom() != null) - // .map(category -> category.getCustom().getType().getId()) - // .collect(Collectors.toList()); - // assertThat(referenceKeys).doesNotContainSequence(referenceIds); - // assertThat(draftsFromPageStage).isCompletedWithValue(expectedResult); - // } - // - // @Test - // void getQuery_ShouldBuildCategoryQuery() { - // // preparation - // final CategorySyncer categorySyncer = - // CategorySyncer.of(mock(SphereClient.class), mock(SphereClient.class), getMockedClock()); - // - // // test - // final CategoryQuery query = categorySyncer.getQuery(); - // - // // assertion - // CategoryQuery expectedQuery = CategoryQuery.of(); - // assertThat(query).isEqualTo(expectedQuery); - // } - // - // @Test - // void syncWithError_ShouldCallErrorCallback() { - // // preparation: category with no key is synced - // final SphereClient sourceClient = mock(SphereClient.class); - // final SphereClient targetClient = mock(SphereClient.class); - // when(sourceClient.getConfig()).thenReturn(SphereApiConfig.of("source-project")); - // when(targetClient.getConfig()).thenReturn(SphereApiConfig.of("target-project")); - // final List categories = - // Collections.singletonList(readObjectFromResource("category-no-key.json", - // Category.class)); - // - // final PagedQueryResult pagedQueryResult = mock(PagedQueryResult.class); - // when(pagedQueryResult.getResults()).thenReturn(categories); - // when(sourceClient.execute(any(CategoryQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(pagedQueryResult)); - // - // // test - // final CategorySyncer categorySyncer = - // CategorySyncer.of(sourceClient, targetClient, mock(Clock.class)); - // categorySyncer.sync(null, true).toCompletableFuture().join(); - // - // // assertion - // final LoggingEvent errorLog = syncerTestLogger.getAllLoggingEvents().get(1); - // assertThat(errorLog.getMessage()) - // .isEqualTo( - // "Error when trying to sync category. Existing key: <>. Update actions: - // []"); - // assertThat(errorLog.getThrowable().get().getMessage()) - // .isEqualTo( - // "CategoryDraft with name: LocalizedString(en -> category-name-1) doesn't have a key. - // Please make sure all category drafts have keys."); - // } - // - // @Test - // void syncWithWarning_ShouldCallWarningCallback() { - // // preparation: old category has category order hint, - // // new category does not have category order hint - // final SphereClient sourceClient = mock(SphereClient.class); - // final SphereClient targetClient = mock(SphereClient.class); - // when(sourceClient.getConfig()).thenReturn(SphereApiConfig.of("source-project")); - // when(targetClient.getConfig()).thenReturn(SphereApiConfig.of("target-project")); - // - // final List sourceCategories = - // Collections.singletonList(readObjectFromResource("category-key-2.json", - // Category.class)); - // final List targetCategories = - // Collections.singletonList( - // readObjectFromResource("category-order-hint.json", Category.class)); - // - // final PagedQueryResult sourcePagedQueryResult = mock(PagedQueryResult.class); - // when(sourcePagedQueryResult.getResults()).thenReturn(sourceCategories); - // when(sourceClient.execute(any(CategoryQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(sourcePagedQueryResult)); - // - // final PagedQueryResult targetPagedQueryResult = mock(PagedQueryResult.class); - // when(targetPagedQueryResult.getResults()).thenReturn(targetCategories); - // when(targetClient.execute(any(CategoryQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(targetPagedQueryResult)); - // when(targetPagedQueryResult.head()).thenReturn(Optional.of(targetCategories.get(0))); - // - // final ResourceKeyIdGraphQlResult resourceKeyIdGraphQlResult = - // mock(ResourceKeyIdGraphQlResult.class); - // when(resourceKeyIdGraphQlResult.getResults()) - // .thenReturn( - // singleton(new ResourceKeyId("categoryKey2", - // "ba81a6da-cf83-435b-a89e-2afab579846f"))); - // when(targetClient.execute(any(ResourceKeyIdGraphQlRequest.class))) - // .thenReturn(CompletableFuture.completedFuture(resourceKeyIdGraphQlResult)); - // - // // test - // final CategorySyncer categorySyncer = - // CategorySyncer.of(sourceClient, targetClient, mock(Clock.class)); - // categorySyncer.sync(null, true).toCompletableFuture().join(); - // - // // assertion - // final LoggingEvent errorLog = syncerTestLogger.getAllLoggingEvents().get(1); - // assertThat(errorLog.getMessage()) - // .isEqualTo("Warning when trying to sync category. Existing key: categoryKey2"); - // assertThat(errorLog.getThrowable().get().getMessage()) - // .isEqualTo( - // format( - // "Cannot unset 'orderHint' field of category with id '%s'.", - // sourceCategories.get(0).getId())); - // } + @Test + void of_ShouldCreateCategorySyncerInstance() { + // test + final ProjectApiRoot projectApiRoot = mock(ProjectApiRoot.class); + final ByProjectKeyCategoriesRequestBuilder byProjectKeyCategoriesRequestBuilder = mock(); + when(projectApiRoot.categories()).thenReturn(byProjectKeyCategoriesRequestBuilder); + final ByProjectKeyCategoriesGet byProjectKeyCategoriesGet = mock(); + when(byProjectKeyCategoriesRequestBuilder.get()).thenReturn(byProjectKeyCategoriesGet); + final CategorySyncer categorySyncer = + CategorySyncer.of(projectApiRoot, projectApiRoot, getMockedClock()); + + // assertions + assertThat(categorySyncer).isNotNull(); + assertThat(categorySyncer.getQuery()).isEqualTo(byProjectKeyCategoriesGet); + assertThat(categorySyncer.getSync()).isExactlyInstanceOf(CategorySync.class); + } + + @Test + void transform_ShouldReplaceCategoryReferenceIdsWithKeys() throws JsonProcessingException { + // preparation + final ProjectApiRoot sourceClient = mock(ProjectApiRoot.class); + final CategorySyncer categorySyncer = + CategorySyncer.of(sourceClient, mock(ProjectApiRoot.class), getMockedClock()); + final List categoryPage = + asList( + readObjectFromResource("category-key-1.json", Category.class), + readObjectFromResource("category-key-2.json", Category.class)); + final List referenceIds = + categoryPage.stream() + .filter(category -> category.getCustom() != null) + .map(category -> category.getCustom().getType().getId()) + .collect(Collectors.toList()); + + final String jsonStringCustomTypes = + "{\"data\":{\"typeDefinitions\":{\"results\":[{\"id\":\"53c4a8b4-754f-4b95-b6f2-3e1e70e3d0c3\",\"key\":\"cat1\"}]}}}"; + + final GraphQLResponse categoriesResult = + readObject(jsonStringCustomTypes, GraphQLResponse.class); + + final ApiHttpResponse response = mock(ApiHttpResponse.class); + when(response.getBody()).thenReturn(categoriesResult); + + final ByProjectKeyGraphqlRequestBuilder byProjectKeyGraphqlRequestBuilder = mock(); + when(sourceClient.graphql()).thenReturn(byProjectKeyGraphqlRequestBuilder); + final ByProjectKeyGraphqlPost byProjectKeyGraphqlPost = mock(); + when(byProjectKeyGraphqlRequestBuilder.post(any(GraphQLRequest.class))) + .thenReturn(byProjectKeyGraphqlPost); + when(byProjectKeyGraphqlPost.execute()).thenReturn(CompletableFuture.completedFuture(response)); + + // test + final CompletionStage> draftsFromPageStage = + categorySyncer.transform(categoryPage); + + // assertions + final List expectedResult = + toCategoryDrafts(sourceClient, referenceIdToKeyCache, categoryPage).join(); + final List referenceKeys = + expectedResult.stream() + .filter(category -> category.getCustom() != null) + .map(category -> category.getCustom().getType().getId()) + .collect(Collectors.toList()); + assertThat(referenceKeys).doesNotContainSequence(referenceIds); + assertThat(draftsFromPageStage).isCompletedWithValue(expectedResult); + } + + @Test + void syncWithError_ShouldCallErrorCallback() { + // preparation: category with no key is synced + final ProjectApiRoot sourceClient = mock(ProjectApiRoot.class); + final ProjectApiRoot targetClient = mock(ProjectApiRoot.class); + final ByProjectKeyCategoriesRequestBuilder byProjectKeyCategoriesRequestBuilder = mock(); + when(sourceClient.categories()).thenReturn(byProjectKeyCategoriesRequestBuilder); + final ByProjectKeyCategoriesGet byProjectKeyCategoriesGet = mock(); + when(byProjectKeyCategoriesRequestBuilder.get()).thenReturn(byProjectKeyCategoriesGet); + when(byProjectKeyCategoriesGet.withSort(anyString())).thenReturn(byProjectKeyCategoriesGet); + when(byProjectKeyCategoriesGet.withLimit(anyInt())).thenReturn(byProjectKeyCategoriesGet); + when(byProjectKeyCategoriesGet.withWithTotal(anyBoolean())) + .thenReturn(byProjectKeyCategoriesGet); + final ApiHttpResponse response = mock(ApiHttpResponse.class); + final List categories = + Collections.singletonList(readObjectFromResource("category-no-key.json", Category.class)); + final CategoryPagedQueryResponse categoryPagedQueryResponse = + CategoryPagedQueryResponseBuilder.of() + .results(categories) + .limit(20L) + .offset(0L) + .count(1L) + .build(); + when(response.getBody()).thenReturn(categoryPagedQueryResponse); + when(byProjectKeyCategoriesGet.execute()) + .thenReturn(CompletableFuture.completedFuture(response)); + + // test + final CategorySyncer categorySyncer = + CategorySyncer.of(sourceClient, targetClient, mock(Clock.class)); + categorySyncer.sync(null, true).toCompletableFuture().join(); + + // assertion + final LoggingEvent errorLog = syncerTestLogger.getAllLoggingEvents().get(1); + assertThat(errorLog.getMessage()) + .isEqualTo( + "Error when trying to sync category. Existing key: <>. Update actions: []"); + assertThat(errorLog.getThrowable().get().getMessage()) + .isEqualTo( + format( + "CategoryDraft with name: %s doesn't have a key. Please make sure all category drafts have keys.", + categories.get(0).getName().toString())); + } + + @Test + void syncWithWarning_ShouldCallWarningCallback() throws JsonProcessingException { + // preparation: old category has category order hint, + // new category does not have category order hint + final ProjectApiRoot sourceClient = mock(ProjectApiRoot.class); + final ByProjectKeyCategoriesRequestBuilder byProjectKeyCategoriesRequestBuilder = mock(); + when(sourceClient.categories()).thenReturn(byProjectKeyCategoriesRequestBuilder); + final ByProjectKeyCategoriesGet byProjectKeyCategoriesGetSource = mock(); + when(byProjectKeyCategoriesRequestBuilder.get()).thenReturn(byProjectKeyCategoriesGetSource); + final ByProjectKeyCategoriesKeyByKeyRequestBuilder + byProjectKeyCategoriesKeyByKeyRequestBuilder = mock(); + when(byProjectKeyCategoriesRequestBuilder.withKey(anyString())) + .thenReturn(byProjectKeyCategoriesKeyByKeyRequestBuilder); + final ByProjectKeyCategoriesKeyByKeyGet byProjectKeyCategoriesKeyByKeyGet = mock(); + when(byProjectKeyCategoriesKeyByKeyRequestBuilder.get()) + .thenReturn(byProjectKeyCategoriesKeyByKeyGet); + when(byProjectKeyCategoriesGetSource.withSort(anyString())) + .thenReturn(byProjectKeyCategoriesGetSource); + when(byProjectKeyCategoriesGetSource.withLimit(anyInt())) + .thenReturn(byProjectKeyCategoriesGetSource); + when(byProjectKeyCategoriesGetSource.withWithTotal(anyBoolean())) + .thenReturn(byProjectKeyCategoriesGetSource); + final List sourceCategories = + Collections.singletonList( + readObjectFromResource("category-order-hint.json", Category.class)); + final ApiHttpResponse sourceResponse = mock(ApiHttpResponse.class); + final CategoryPagedQueryResponse categoryPagedQueryResponse = + CategoryPagedQueryResponseBuilder.of() + .results(sourceCategories) + .limit(20L) + .offset(0L) + .count(1L) + .build(); + when(sourceResponse.getBody()).thenReturn(categoryPagedQueryResponse); + when(byProjectKeyCategoriesGetSource.execute()) + .thenReturn(CompletableFuture.completedFuture(sourceResponse)); + when(byProjectKeyCategoriesKeyByKeyGet.execute()) + .thenReturn( + CompletableFuture.completedFuture( + new ApiHttpResponse(200, null, sourceCategories.get(0)))); + + final ProjectApiRoot targetClient = mock(ProjectApiRoot.class); + final ByProjectKeyCategoriesGet byProjectKeyCategoriesGetTarget = mock(); + when(targetClient.categories()).thenReturn(byProjectKeyCategoriesRequestBuilder); + when(byProjectKeyCategoriesRequestBuilder.get()).thenReturn(byProjectKeyCategoriesGetTarget); + when(byProjectKeyCategoriesGetTarget.withWhere(anyString())) + .thenReturn(byProjectKeyCategoriesGetTarget); + when(byProjectKeyCategoriesGetTarget.withPredicateVar(anyString(), any())) + .thenReturn(byProjectKeyCategoriesGetTarget); + when(byProjectKeyCategoriesGetTarget.withLimit(anyInt())) + .thenReturn(byProjectKeyCategoriesGetTarget); + when(byProjectKeyCategoriesGetTarget.withWithTotal(anyBoolean())) + .thenReturn(byProjectKeyCategoriesGetTarget); + when(byProjectKeyCategoriesGetTarget.withSort(anyString())) + .thenReturn(byProjectKeyCategoriesGetTarget); + + final List targetCategories = + Collections.singletonList(readObjectFromResource("category-key-2.json", Category.class)); + final ApiHttpResponse targetResponse = mock(ApiHttpResponse.class); + final CategoryPagedQueryResponse categoryPagedQueryResponseTarget = + CategoryPagedQueryResponseBuilder.of() + .results(targetCategories) + .limit(20L) + .offset(0L) + .count(1L) + .build(); + when(targetResponse.getBody()).thenReturn(categoryPagedQueryResponseTarget); + when(byProjectKeyCategoriesGetTarget.execute()) + .thenReturn(CompletableFuture.completedFuture(targetResponse)); + + final String jsonStringCustomTypes = + "{\"data\":{\"categories\":{\"results\":[{\"id\":\"ba81a6da-cf83-435b-a89e-2afab579846f\",\"key\":\"categoryKey2\"}]}}}"; + + final GraphQLResponse categoriesResult = + readObject(jsonStringCustomTypes, GraphQLResponse.class); + + final ApiHttpResponse graphQLResponse = mock(ApiHttpResponse.class); + when(graphQLResponse.getBody()).thenReturn(categoriesResult); + + final ByProjectKeyGraphqlRequestBuilder byProjectKeyGraphqlRequestBuilder = mock(); + when(targetClient.graphql()).thenReturn(byProjectKeyGraphqlRequestBuilder); + final ByProjectKeyGraphqlPost byProjectKeyGraphqlPost = mock(); + when(byProjectKeyGraphqlRequestBuilder.post(any(GraphQLRequest.class))) + .thenReturn(byProjectKeyGraphqlPost); + when(byProjectKeyGraphqlPost.execute()) + .thenReturn(CompletableFuture.completedFuture(graphQLResponse)); + + // test + final CategorySyncer categorySyncer = + CategorySyncer.of(sourceClient, targetClient, mock(Clock.class)); + categorySyncer.sync(null, true).toCompletableFuture().join(); + + // assertion + final LoggingEvent errorLog = syncerTestLogger.getAllLoggingEvents().get(1); + assertThat(errorLog.getMessage()) + .isEqualTo("Warning when trying to sync category. Existing key: categoryKey2"); + assertThat(errorLog.getThrowable().get().getMessage()) + .isEqualTo( + format( + "Cannot unset 'orderHint' field of category with id '%s'.", + sourceCategories.get(0).getId())); + } } diff --git a/src/test/java/com/commercetools/project/sync/util/TestUtils.java b/src/test/java/com/commercetools/project/sync/util/TestUtils.java index dacbbbed..810fccd2 100644 --- a/src/test/java/com/commercetools/project/sync/util/TestUtils.java +++ b/src/test/java/com/commercetools/project/sync/util/TestUtils.java @@ -29,6 +29,7 @@ import io.vrap.rmf.base.client.ApiHttpMethod; import io.vrap.rmf.base.client.ApiHttpResponse; import io.vrap.rmf.base.client.error.BadGatewayException; +import io.vrap.rmf.base.client.utils.json.JsonUtils; import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; @@ -211,6 +212,12 @@ public static T readObjectFromResource(final String resourcePath, final Clas return fromInputStream(resourceAsStream, objectType); } + public static T readObject(final String jsonString, final Class objectType) + throws JsonProcessingException { + final ObjectMapper objectMapper = JsonUtils.getConfiguredObjectMapper(); + return objectMapper.readValue(jsonString, objectType); + } + public static String readStringFromFile(final String resourcePath) { final InputStream resourceAsStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(resourcePath); From ba5fc2c2c257d2c7e7e45e623e5cb35afa67e963 Mon Sep 17 00:00:00 2001 From: lojzatran Date: Thu, 19 Oct 2023 13:05:31 +0200 Subject: [PATCH 08/14] DEVX-247 fix spotbugs --- build.gradle | 2 +- .../java/com/commercetools/project/sync/SyncerFactoryTest.java | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 629aa075..25ff6dd9 100644 --- a/build.gradle +++ b/build.gradle @@ -14,7 +14,7 @@ plugins { id "com.github.ben-manes.versions" version '0.47.0' id 'com.adarshr.test-logger' version '3.2.0' id 'com.diffplug.spotless' version '6.21.0' - id "com.github.spotbugs" version "5.1.3" + id "com.github.spotbugs" version "5.2.1" } apply from: "$rootDir/gradle-scripts/extensions.gradle" diff --git a/src/test/java/com/commercetools/project/sync/SyncerFactoryTest.java b/src/test/java/com/commercetools/project/sync/SyncerFactoryTest.java index f178d25b..98d3d968 100644 --- a/src/test/java/com/commercetools/project/sync/SyncerFactoryTest.java +++ b/src/test/java/com/commercetools/project/sync/SyncerFactoryTest.java @@ -813,7 +813,6 @@ void sync_AsProductTypesDeltaSync_ShouldBuildSyncerAndExecuteSync() { @SuppressWarnings("unchecked") void sync_AsTypesDeltaSync_ShouldBuildSyncerAndExecuteSync() { // preparation - final ZonedDateTime currentCtpTimestamp = ZonedDateTime.now(); stubClientsCustomObjectService(targetClient, ZonedDateTime.now()); final SyncerFactory syncerFactory = From 0a5b757d9ffa5c49a768e73a9d312467cb0c212f Mon Sep 17 00:00:00 2001 From: lojzatran Date: Thu, 19 Oct 2023 16:18:25 +0200 Subject: [PATCH 09/14] DEVX-247 rename variable --- .../project/sync/category/CategorySyncerTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/commercetools/project/sync/category/CategorySyncerTest.java b/src/test/java/com/commercetools/project/sync/category/CategorySyncerTest.java index a18d531f..6d74f9ec 100644 --- a/src/test/java/com/commercetools/project/sync/category/CategorySyncerTest.java +++ b/src/test/java/com/commercetools/project/sync/category/CategorySyncerTest.java @@ -86,11 +86,11 @@ void transform_ShouldReplaceCategoryReferenceIdsWithKeys() throws JsonProcessing final String jsonStringCustomTypes = "{\"data\":{\"typeDefinitions\":{\"results\":[{\"id\":\"53c4a8b4-754f-4b95-b6f2-3e1e70e3d0c3\",\"key\":\"cat1\"}]}}}"; - final GraphQLResponse categoriesResult = + final GraphQLResponse customTypesResult = readObject(jsonStringCustomTypes, GraphQLResponse.class); final ApiHttpResponse response = mock(ApiHttpResponse.class); - when(response.getBody()).thenReturn(categoriesResult); + when(response.getBody()).thenReturn(customTypesResult); final ByProjectKeyGraphqlRequestBuilder byProjectKeyGraphqlRequestBuilder = mock(); when(sourceClient.graphql()).thenReturn(byProjectKeyGraphqlRequestBuilder); From 8b07dfe3598b02011c8ca6065bf6d6516b4f725e Mon Sep 17 00:00:00 2001 From: lojzatran Date: Thu, 19 Oct 2023 16:18:50 +0200 Subject: [PATCH 10/14] DEVX-247 rename variable --- .../project/sync/category/CategorySyncerTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/commercetools/project/sync/category/CategorySyncerTest.java b/src/test/java/com/commercetools/project/sync/category/CategorySyncerTest.java index 6d74f9ec..d10f2c50 100644 --- a/src/test/java/com/commercetools/project/sync/category/CategorySyncerTest.java +++ b/src/test/java/com/commercetools/project/sync/category/CategorySyncerTest.java @@ -232,11 +232,11 @@ void syncWithWarning_ShouldCallWarningCallback() throws JsonProcessingException final String jsonStringCustomTypes = "{\"data\":{\"categories\":{\"results\":[{\"id\":\"ba81a6da-cf83-435b-a89e-2afab579846f\",\"key\":\"categoryKey2\"}]}}}"; - final GraphQLResponse categoriesResult = + final GraphQLResponse customTypesResult = readObject(jsonStringCustomTypes, GraphQLResponse.class); final ApiHttpResponse graphQLResponse = mock(ApiHttpResponse.class); - when(graphQLResponse.getBody()).thenReturn(categoriesResult); + when(graphQLResponse.getBody()).thenReturn(customTypesResult); final ByProjectKeyGraphqlRequestBuilder byProjectKeyGraphqlRequestBuilder = mock(); when(targetClient.graphql()).thenReturn(byProjectKeyGraphqlRequestBuilder); From d28c606c2ea9381c57648ff519ca975be8f0395a Mon Sep 17 00:00:00 2001 From: lojzatran Date: Fri, 20 Oct 2023 14:46:30 +0200 Subject: [PATCH 11/14] DEVX-248 migrate inventory syncer --- .../sync/InventorySyncMultiChannelIT.java | 455 ++++++++++-------- .../inventoryentry/InventoryEntrySyncer.java | 2 - .../InventoryEntrySyncerTest.java | 268 ++++++----- .../project/sync/util/TestUtils.java | 24 +- 4 files changed, 428 insertions(+), 321 deletions(-) diff --git a/src/integration-test/java/com/commercetools/project/sync/InventorySyncMultiChannelIT.java b/src/integration-test/java/com/commercetools/project/sync/InventorySyncMultiChannelIT.java index 016efbd4..4b7269b4 100644 --- a/src/integration-test/java/com/commercetools/project/sync/InventorySyncMultiChannelIT.java +++ b/src/integration-test/java/com/commercetools/project/sync/InventorySyncMultiChannelIT.java @@ -1,206 +1,249 @@ -// package com.commercetools.project.sync; -// -// import static com.commercetools.project.sync.util.CtpClientUtils.CTP_SOURCE_CLIENT; -// import static com.commercetools.project.sync.util.CtpClientUtils.CTP_TARGET_CLIENT; -// import static com.commercetools.project.sync.util.IntegrationTestUtils.cleanUpProjects; -// import static com.commercetools.project.sync.util.IntegrationTestUtils.createITSyncerFactory; -// import static java.util.Collections.singletonList; -// import static org.assertj.core.api.Assertions.assertThat; -// -// import com.commercetools.project.sync.inventoryentry.InventoryEntrySyncer; -// import com.fasterxml.jackson.databind.JsonNode; -// import com.fasterxml.jackson.databind.node.JsonNodeFactory; -// import io.sphere.sdk.channels.Channel; -// import io.sphere.sdk.channels.ChannelDraft; -// import io.sphere.sdk.channels.ChannelRole; -// import io.sphere.sdk.channels.commands.ChannelCreateCommand; -// import io.sphere.sdk.client.SphereClient; -// import io.sphere.sdk.inventory.InventoryEntry; -// import io.sphere.sdk.inventory.InventoryEntryDraft; -// import io.sphere.sdk.inventory.InventoryEntryDraftBuilder; -// import io.sphere.sdk.inventory.commands.InventoryEntryCreateCommand; -// import io.sphere.sdk.models.LocalizedString; -// import io.sphere.sdk.models.Reference; -// import io.sphere.sdk.types.CustomFieldsDraft; -// import io.sphere.sdk.types.FieldDefinition; -// import io.sphere.sdk.types.StringFieldType; -// import io.sphere.sdk.types.TypeDraft; -// import io.sphere.sdk.types.TypeDraftBuilder; -// import io.sphere.sdk.types.commands.TypeCreateCommand; -// import java.util.Collections; -// import java.util.HashMap; -// import java.util.Locale; -// import java.util.Map; -// import java.util.concurrent.CompletableFuture; -// import java.util.stream.IntStream; -// import javax.annotation.Nonnull; -// import org.junit.jupiter.api.BeforeEach; -// import org.junit.jupiter.api.Disabled; -// import org.junit.jupiter.api.Test; -// import uk.org.lidalia.slf4jext.Level; -// import uk.org.lidalia.slf4jtest.TestLogger; -// import uk.org.lidalia.slf4jtest.TestLoggerFactory; -// -// @Disabled( -// "Disabled for normal builds, " -// + "This scenario created to evaluate multiple channel use case" -// + "see: https://github.com/commercetools/commercetools-project-sync/issues/301") -// public class InventorySyncMultiChannelIT { -// private static final TestLogger testLogger = -// TestLoggerFactory.getTestLogger(InventoryEntrySyncer.class); -// -// public static final String SKU_1 = "SKU_ONE"; -// public static final String SKU_2 = "SKU_TWO"; -// public static final String SUPPLY_CHANNEL_KEY_1 = "channel-key_1"; -// public static final String SUPPLY_CHANNEL_KEY_2 = "channel-key_2"; -// -// public static final String CUSTOM_TYPE = "inventory-custom-type-name"; -// public static final String CUSTOM_FIELD_NAME = "inventory-custom-field-1"; -// -// @BeforeEach -// void setup() { -// testLogger.clearAll(); -// cleanUpProjects(CTP_SOURCE_CLIENT, CTP_TARGET_CLIENT); -// create249InventoryEntry(CTP_SOURCE_CLIENT); -// create249InventoryEntry(CTP_TARGET_CLIENT); -// setupProjectData(CTP_SOURCE_CLIENT); -// setupProjectData(CTP_TARGET_CLIENT); -// } -// -// private void setupProjectData(SphereClient sphereClient) { -// final ChannelDraft channelDraft1 = -// ChannelDraft.of(SUPPLY_CHANNEL_KEY_1).withRoles(ChannelRole.INVENTORY_SUPPLY); -// final ChannelDraft channelDraft2 = -// ChannelDraft.of(SUPPLY_CHANNEL_KEY_2).withRoles(ChannelRole.INVENTORY_SUPPLY); -// -// final String channelId1 = -// sphereClient -// .execute(ChannelCreateCommand.of(channelDraft1)) -// .toCompletableFuture() -// .join() -// .getId(); -// final String channelId2 = -// sphereClient -// .execute(ChannelCreateCommand.of(channelDraft2)) -// .toCompletableFuture() -// .join() -// .getId(); -// -// final Reference supplyChannelReference1 = Channel.referenceOfId(channelId1); -// final Reference supplyChannelReference2 = Channel.referenceOfId(channelId2); -// -// createInventoriesCustomType(sphereClient); -// -// // NOTE: There can only be one inventory entry for the combination of sku and supplyChannel. -// final InventoryEntryDraft draft1 = InventoryEntryDraftBuilder.of(SKU_1, 0L).build(); -// final InventoryEntryDraft draft2 = -// InventoryEntryDraftBuilder.of(SKU_1, 0L) -// .supplyChannel(supplyChannelReference1) -// .custom(CustomFieldsDraft.ofTypeKeyAndJson(CUSTOM_TYPE, getMockCustomFieldsJsons())) -// .build(); -// final InventoryEntryDraft draft3 = -// InventoryEntryDraftBuilder.of(SKU_1, 1L) -// .supplyChannel(supplyChannelReference2) -// .custom(CustomFieldsDraft.ofTypeKeyAndJson(CUSTOM_TYPE, getMockCustomFieldsJsons())) -// .build(); -// -// final InventoryEntryDraft draft4 = InventoryEntryDraftBuilder.of(SKU_2, 0L).build(); -// final InventoryEntryDraft draft5 = -// InventoryEntryDraftBuilder.of(SKU_2, 0L) -// .supplyChannel(supplyChannelReference1) -// .custom(CustomFieldsDraft.ofTypeKeyAndJson(CUSTOM_TYPE, getMockCustomFieldsJsons())) -// .build(); -// final InventoryEntryDraft draft6 = -// InventoryEntryDraftBuilder.of(SKU_2, 1L) -// .supplyChannel(supplyChannelReference2) -// .custom(CustomFieldsDraft.ofTypeKeyAndJson(CUSTOM_TYPE, getMockCustomFieldsJsons())) -// .build(); -// -// CompletableFuture.allOf( -// sphereClient.execute(InventoryEntryCreateCommand.of(draft1)).toCompletableFuture(), -// sphereClient.execute(InventoryEntryCreateCommand.of(draft2)).toCompletableFuture(), -// sphereClient.execute(InventoryEntryCreateCommand.of(draft3)).toCompletableFuture(), -// sphereClient.execute(InventoryEntryCreateCommand.of(draft4)).toCompletableFuture(), -// sphereClient.execute(InventoryEntryCreateCommand.of(draft5)).toCompletableFuture(), -// sphereClient.execute(InventoryEntryCreateCommand.of(draft6)).toCompletableFuture()) -// .join(); -// } -// -// private static void createInventoriesCustomType(@Nonnull final SphereClient ctpClient) { -// final FieldDefinition fieldDefinition = -// FieldDefinition.of( -// StringFieldType.of(), -// CUSTOM_FIELD_NAME, -// LocalizedString.of(Locale.ENGLISH, CUSTOM_FIELD_NAME), -// false); -// final TypeDraft typeDraft = -// TypeDraftBuilder.of( -// CUSTOM_TYPE, -// LocalizedString.of(Locale.ENGLISH, CUSTOM_TYPE), -// Collections.singleton(InventoryEntry.resourceTypeId())) -// .fieldDefinitions(singletonList(fieldDefinition)) -// .build(); -// ctpClient.execute(TypeCreateCommand.of(typeDraft)).toCompletableFuture().join(); -// } -// -// private static Map getMockCustomFieldsJsons() { -// final Map customFieldsJsons = new HashMap<>(); -// customFieldsJsons.put(CUSTOM_FIELD_NAME, JsonNodeFactory.instance.textNode("customValue")); -// return customFieldsJsons; -// } -// -// private void create249InventoryEntry(SphereClient sphereClient) { -// CompletableFuture.allOf( -// IntStream.range(0, 10) -// .mapToObj( -// value -> -// sphereClient -// .execute( -// InventoryEntryCreateCommand.of( -// InventoryEntryDraftBuilder.of("SKU_" + value, 1L).build())) -// .toCompletableFuture()) -// .toArray(CompletableFuture[]::new)) -// .join(); -// -// CompletableFuture.allOf( -// IntStream.range(0, 251) -// .mapToObj(value -> create(sphereClient, value)) -// .toArray(CompletableFuture[]::new)) -// .join(); -// } -// -// private CompletableFuture create(SphereClient sphereClient, int value) { -// final ChannelDraft channelDraft1 = -// ChannelDraft.of("other-channel-key_" + value).withRoles(ChannelRole.INVENTORY_SUPPLY); -// -// final String channelId = -// sphereClient -// .execute(ChannelCreateCommand.of(channelDraft1)) -// .toCompletableFuture() -// .join() -// .getId(); -// -// final Reference supplyChannelReference = Channel.referenceOfId(channelId); -// -// return sphereClient -// .execute( -// InventoryEntryCreateCommand.of( -// InventoryEntryDraftBuilder.of("SKU_CHANNEL", 0L) -// .supplyChannel(supplyChannelReference) -// .build())) -// .toCompletableFuture(); -// } -// -// @Test -// void run_asInventoryFullSync_ShouldNotReturnAnError() { -// // test -// CliRunner.of().run(new String[] {"-s", "inventoryEntries", "-f"}, createITSyncerFactory()); -// -// // assertions -// assertThat(testLogger.getAllLoggingEvents()) -// .allMatch(loggingEvent -> !Level.ERROR.equals(loggingEvent.getLevel())); -// -// // Every sync module is expected to have 2 logs (start and stats summary) -// assertThat(testLogger.getAllLoggingEvents()).hasSize(2); -// } -// } +package com.commercetools.project.sync; + +import static com.commercetools.project.sync.util.CtpClientUtils.CTP_SOURCE_CLIENT; +import static com.commercetools.project.sync.util.CtpClientUtils.CTP_TARGET_CLIENT; +import static com.commercetools.project.sync.util.IntegrationTestUtils.cleanUpProjects; +import static com.commercetools.project.sync.util.IntegrationTestUtils.createITSyncerFactory; +import static org.assertj.core.api.Assertions.assertThat; + +import com.commercetools.api.client.ProjectApiRoot; +import com.commercetools.api.models.channel.Channel; +import com.commercetools.api.models.channel.ChannelDraft; +import com.commercetools.api.models.channel.ChannelDraftBuilder; +import com.commercetools.api.models.channel.ChannelRoleEnum; +import com.commercetools.api.models.common.LocalizedString; +import com.commercetools.api.models.inventory.InventoryEntry; +import com.commercetools.api.models.inventory.InventoryEntryDraft; +import com.commercetools.api.models.inventory.InventoryEntryDraftBuilder; +import com.commercetools.api.models.type.CustomFieldsDraftBuilder; +import com.commercetools.api.models.type.FieldContainer; +import com.commercetools.api.models.type.FieldContainerBuilder; +import com.commercetools.api.models.type.FieldDefinition; +import com.commercetools.api.models.type.FieldDefinitionBuilder; +import com.commercetools.api.models.type.FieldTypeBuilder; +import com.commercetools.api.models.type.ResourceTypeId; +import com.commercetools.api.models.type.TypeDraft; +import com.commercetools.api.models.type.TypeDraftBuilder; +import com.commercetools.project.sync.inventoryentry.InventoryEntrySyncer; +import com.fasterxml.jackson.databind.node.JsonNodeFactory; +import io.vrap.rmf.base.client.ApiHttpResponse; +import java.util.concurrent.CompletableFuture; +import java.util.stream.IntStream; +import javax.annotation.Nonnull; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import uk.org.lidalia.slf4jext.Level; +import uk.org.lidalia.slf4jtest.TestLogger; +import uk.org.lidalia.slf4jtest.TestLoggerFactory; + +@Disabled( + "Disabled for normal builds, " + + "This scenario created to evaluate multiple channel use case" + + "see: https://github.com/commercetools/commercetools-project-sync/issues/301") +public class InventorySyncMultiChannelIT { + private static final TestLogger testLogger = + TestLoggerFactory.getTestLogger(InventoryEntrySyncer.class); + + public static final String SKU_1 = "SKU_ONE"; + public static final String SKU_2 = "SKU_TWO"; + public static final String SUPPLY_CHANNEL_KEY_1 = "channel-key_1"; + public static final String SUPPLY_CHANNEL_KEY_2 = "channel-key_2"; + + public static final String CUSTOM_TYPE = "inventory-custom-type-name"; + public static final String CUSTOM_FIELD_NAME = "inventory-custom-field-1"; + + @BeforeEach + void setup() { + testLogger.clearAll(); + cleanUpProjects(CTP_SOURCE_CLIENT, CTP_TARGET_CLIENT); + create249InventoryEntry(CTP_SOURCE_CLIENT); + create249InventoryEntry(CTP_TARGET_CLIENT); + setupProjectData(CTP_SOURCE_CLIENT); + setupProjectData(CTP_TARGET_CLIENT); + } + + private void setupProjectData(ProjectApiRoot projectApiRoot) { + final ChannelDraft channelDraft1 = + ChannelDraftBuilder.of() + .key(SUPPLY_CHANNEL_KEY_1) + .roles(ChannelRoleEnum.INVENTORY_SUPPLY) + .build(); + final ChannelDraft channelDraft2 = + ChannelDraftBuilder.of() + .key(SUPPLY_CHANNEL_KEY_2) + .roles(ChannelRoleEnum.INVENTORY_SUPPLY) + .build(); + + final Channel channel1 = + projectApiRoot + .channels() + .create(channelDraft1) + .execute() + .thenApply(ApiHttpResponse::getBody) + .toCompletableFuture() + .join(); + final Channel channel2 = + projectApiRoot + .channels() + .create(channelDraft2) + .execute() + .thenApply(ApiHttpResponse::getBody) + .toCompletableFuture() + .join(); + + createInventoriesCustomType(projectApiRoot); + + // NOTE: There can only be one inventory entry for the combination of sku and supplyChannel. + final InventoryEntryDraft draft1 = + InventoryEntryDraftBuilder.of().sku(SKU_1).quantityOnStock(0L).build(); + final InventoryEntryDraft draft2 = + InventoryEntryDraftBuilder.of() + .sku(SKU_1) + .quantityOnStock(0L) + .supplyChannel(channel1.toResourceIdentifier()) + .custom( + CustomFieldsDraftBuilder.of() + .type(builder -> builder.key(CUSTOM_TYPE)) + .fields(getMockFieldContainer()) + .build()) + .build(); + final InventoryEntryDraft draft3 = + InventoryEntryDraftBuilder.of() + .sku(SKU_1) + .quantityOnStock(1L) + .supplyChannel(channel2.toResourceIdentifier()) + .custom( + CustomFieldsDraftBuilder.of() + .type(builder -> builder.key(CUSTOM_TYPE)) + .fields(getMockFieldContainer()) + .build()) + .build(); + + final InventoryEntryDraft draft4 = + InventoryEntryDraftBuilder.of().sku(SKU_2).quantityOnStock(0L).build(); + final InventoryEntryDraft draft5 = + InventoryEntryDraftBuilder.of() + .sku(SKU_2) + .quantityOnStock(0L) + .supplyChannel(channel1.toResourceIdentifier()) + .custom( + CustomFieldsDraftBuilder.of() + .type(builder -> builder.key(CUSTOM_TYPE)) + .fields(getMockFieldContainer()) + .build()) + .build(); + final InventoryEntryDraft draft6 = + InventoryEntryDraftBuilder.of() + .sku(SKU_2) + .quantityOnStock(1L) + .supplyChannel(channel2.toResourceIdentifier()) + .custom( + CustomFieldsDraftBuilder.of() + .type(builder -> builder.key(CUSTOM_TYPE)) + .fields(getMockFieldContainer()) + .build()) + .build(); + + CompletableFuture.allOf( + projectApiRoot.inventory().create(draft1).execute().toCompletableFuture(), + projectApiRoot.inventory().create(draft2).execute().toCompletableFuture(), + projectApiRoot.inventory().create(draft3).execute().toCompletableFuture(), + projectApiRoot.inventory().create(draft4).execute().toCompletableFuture(), + projectApiRoot.inventory().create(draft5).execute().toCompletableFuture(), + projectApiRoot.inventory().create(draft6).execute().toCompletableFuture()) + .join(); + } + + private static void createInventoriesCustomType(@Nonnull final ProjectApiRoot ctpClient) { + final FieldDefinition fieldDefinition = + FieldDefinitionBuilder.of() + .name(CUSTOM_FIELD_NAME) + .label(LocalizedString.ofEnglish(CUSTOM_FIELD_NAME)) + .required(false) + .type(FieldTypeBuilder.of().stringBuilder().build()) + .build(); + + final TypeDraft typeDraft = + TypeDraftBuilder.of() + .key(CUSTOM_TYPE) + .name(LocalizedString.ofEnglish(CUSTOM_TYPE)) + .resourceTypeIds(ResourceTypeId.INVENTORY_ENTRY) + .fieldDefinitions(fieldDefinition) + .build(); + + ctpClient.types().create(typeDraft).execute().toCompletableFuture().join(); + } + + private static FieldContainer getMockFieldContainer() { + return FieldContainerBuilder.of() + .addValue(CUSTOM_FIELD_NAME, JsonNodeFactory.instance.textNode("customValue")) + .build(); + } + + private void create249InventoryEntry(ProjectApiRoot projectApiRoot) { + CompletableFuture.allOf( + IntStream.range(0, 10) + .mapToObj( + value -> + projectApiRoot + .inventory() + .create( + InventoryEntryDraftBuilder.of() + .sku("SKU_" + value) + .quantityOnStock(1L) + .build()) + .execute() + .toCompletableFuture()) + .toArray(CompletableFuture[]::new)) + .join(); + + CompletableFuture.allOf( + IntStream.range(0, 251) + .mapToObj(value -> create(projectApiRoot, value)) + .toArray(CompletableFuture[]::new)) + .join(); + } + + private CompletableFuture create(ProjectApiRoot projectApiRoot, int value) { + final ChannelDraft channelDraft1 = + ChannelDraftBuilder.of() + .key("other-channel-key_" + value) + .roles(ChannelRoleEnum.INVENTORY_SUPPLY) + .build(); + + final Channel channel = + projectApiRoot + .channels() + .create(channelDraft1) + .execute() + .thenApply(ApiHttpResponse::getBody) + .toCompletableFuture() + .join(); + + return projectApiRoot + .inventory() + .create( + InventoryEntryDraftBuilder.of() + .supplyChannel(channel.toResourceIdentifier()) + .sku("SKU_CHANNEL") + .quantityOnStock(0L) + .build()) + .execute() + .thenApply(ApiHttpResponse::getBody) + .toCompletableFuture(); + } + + @Test + void run_asInventoryFullSync_ShouldNotReturnAnError() { + // test + CliRunner.of().run(new String[] {"-s", "inventoryEntries", "-f"}, createITSyncerFactory()); + + // assertions + assertThat(testLogger.getAllLoggingEvents()) + .allMatch(loggingEvent -> !Level.ERROR.equals(loggingEvent.getLevel())); + + // Every sync module is expected to have 2 logs (start and stats summary) + assertThat(testLogger.getAllLoggingEvents()).hasSize(2); + } +} diff --git a/src/main/java/com/commercetools/project/sync/inventoryentry/InventoryEntrySyncer.java b/src/main/java/com/commercetools/project/sync/inventoryentry/InventoryEntrySyncer.java index 44518836..ea146de9 100644 --- a/src/main/java/com/commercetools/project/sync/inventoryentry/InventoryEntrySyncer.java +++ b/src/main/java/com/commercetools/project/sync/inventoryentry/InventoryEntrySyncer.java @@ -29,8 +29,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -// This class compiles but not tested yet -// TODO: Test class and adjust logic if needed public final class InventoryEntrySyncer extends Syncer< InventoryEntry, diff --git a/src/test/java/com/commercetools/project/sync/inventoryentry/InventoryEntrySyncerTest.java b/src/test/java/com/commercetools/project/sync/inventoryentry/InventoryEntrySyncerTest.java index 8c056d6c..4f903432 100644 --- a/src/test/java/com/commercetools/project/sync/inventoryentry/InventoryEntrySyncerTest.java +++ b/src/test/java/com/commercetools/project/sync/inventoryentry/InventoryEntrySyncerTest.java @@ -1,13 +1,44 @@ package com.commercetools.project.sync.inventoryentry; +import static com.commercetools.project.sync.util.TestUtils.*; +import static com.commercetools.sync.inventories.utils.InventoryTransformUtils.toInventoryEntryDrafts; +import static java.util.Arrays.asList; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import com.commercetools.api.client.ByProjectKeyGraphqlPost; +import com.commercetools.api.client.ByProjectKeyGraphqlRequestBuilder; +import com.commercetools.api.client.ByProjectKeyInventoryGet; +import com.commercetools.api.client.ByProjectKeyInventoryRequestBuilder; +import com.commercetools.api.client.ProjectApiRoot; +import com.commercetools.api.models.graph_ql.GraphQLRequest; +import com.commercetools.api.models.graph_ql.GraphQLResponse; +import com.commercetools.api.models.inventory.InventoryEntry; +import com.commercetools.api.models.inventory.InventoryEntryDraft; +import com.commercetools.api.models.inventory.InventoryPagedQueryResponse; +import com.commercetools.api.models.inventory.InventoryPagedQueryResponseBuilder; import com.commercetools.sync.commons.utils.CaffeineReferenceIdToKeyCacheImpl; import com.commercetools.sync.commons.utils.ReferenceIdToKeyCache; +import com.commercetools.sync.inventories.InventorySync; +import com.fasterxml.jackson.core.JsonProcessingException; +import io.vrap.rmf.base.client.ApiHttpResponse; +import java.time.Clock; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionStage; +import java.util.stream.Collectors; +import java.util.stream.Stream; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import uk.org.lidalia.slf4jtest.LoggingEvent; import uk.org.lidalia.slf4jtest.TestLogger; import uk.org.lidalia.slf4jtest.TestLoggerFactory; -// These tests aren't migrated -// TODO: Migrate tests class InventoryEntrySyncerTest { private final TestLogger syncerTestLogger = @@ -20,111 +51,130 @@ void setup() { syncerTestLogger.clearAll(); } - // @Test - // void of_ShouldCreateInventoryEntrySyncerInstance() { - // // test - // final InventoryEntrySyncer inventorySyncer = - // InventoryEntrySyncer.of( - // mock(SphereClient.class), mock(SphereClient.class), getMockedClock()); - // - // // assertions - // assertThat(inventorySyncer).isNotNull(); - // assertThat(inventorySyncer.getSync()).isInstanceOf(InventorySync.class); - // } - // - // @Test - // void transform_ShouldReplaceInventoryEntryReferenceIdsWithKeys() { - // // preparation - // final SphereClient sourceClient = mock(SphereClient.class); - // final InventoryEntrySyncer inventoryEntrySyncer = - // InventoryEntrySyncer.of(sourceClient, mock(SphereClient.class), getMockedClock()); - // final List inventoryPage = - // asList( - // readObjectFromResource("inventory-sku-1.json", InventoryEntry.class), - // readObjectFromResource("inventory-sku-2.json", InventoryEntry.class)); - // final List referenceIds = - // inventoryPage.stream() - // .filter(inventoryEntry -> inventoryEntry.getSupplyChannel() != null) - // .filter(inventoryEntry -> inventoryEntry.getCustom() != null) - // .flatMap( - // inventoryEntry -> - // Stream.of( - // inventoryEntry.getCustom().getType().getId(), - // inventoryEntry.getSupplyChannel().getId())) - // .collect(Collectors.toList()); - // - // final String jsonStringCustomTypes = - // "{\"results\":[{\"id\":\"02e915e7-7763-48d1-83bd-d4e940a1a368\"," - // + "\"key\":\"test-custom-type-key\"} ]}"; - // final ResourceKeyIdGraphQlResult customTypesResult = - // SphereJsonUtils.readObject(jsonStringCustomTypes, ResourceKeyIdGraphQlResult.class); - // - // final String jsonStringSupplyChannels = - // "{\"results\":[{\"id\":\"5c0516b5-f506-4b6a-b4d1-c06ca29ab7e1\"," - // + "\"key\":\"test-channel-key\"} ]}"; - // final ResourceKeyIdGraphQlResult supplyChannelsResult = - // SphereJsonUtils.readObject(jsonStringSupplyChannels, ResourceKeyIdGraphQlResult.class); - // - // when(sourceClient.execute(any(ResourceIdsGraphQlRequest.class))) - // .thenReturn(CompletableFuture.completedFuture(customTypesResult)) - // .thenReturn(CompletableFuture.completedFuture(supplyChannelsResult)); - // - // // test - // final CompletionStage> draftsFromPageStage = - // inventoryEntrySyncer.transform(inventoryPage); - // - // // assertions - // final List expectedResult = - // toInventoryEntryDrafts(sourceClient, referenceIdToKeyCache, inventoryPage).join(); - // final List referenceKeys = - // expectedResult.stream() - // .filter(inventoryEntry -> inventoryEntry.getSupplyChannel() != null) - // .filter(inventoryEntry -> inventoryEntry.getCustom() != null) - // .flatMap( - // inventoryEntry -> - // Stream.of( - // inventoryEntry.getCustom().getType().getId(), - // inventoryEntry.getSupplyChannel().getId())) - // .collect(Collectors.toList()); - // assertThat(referenceKeys).doesNotContainAnyElementsOf(referenceIds); - // assertThat(draftsFromPageStage).isCompletedWithValue(expectedResult); - // } - // - // @Test - // void syncWithError_ShouldCallErrorCallback() { - // // preparation: inventory entry with no key is synced - // final SphereClient sourceClient = mock(SphereClient.class); - // final SphereClient targetClient = mock(SphereClient.class); - // when(sourceClient.getConfig()).thenReturn(SphereApiConfig.of("source-project")); - // when(targetClient.getConfig()).thenReturn(SphereApiConfig.of("target-project")); - // final List inventoryEntries = - // Collections.singletonList( - // readObjectFromResource("inventory-no-sku.json", InventoryEntry.class)); - // - // final PagedQueryResult pagedQueryResult = mock(PagedQueryResult.class); - // when(pagedQueryResult.getResults()).thenReturn(inventoryEntries); - // when(sourceClient.execute(any(InventoryEntryQuery.class))) - // .thenReturn(CompletableFuture.completedFuture(pagedQueryResult)); - // - // mockResourceIdsGraphQlRequest( - // sourceClient, "4db98ea6-38dc-4ccb-b20f-466e1566567h", "customTypeKey"); - // mockResourceIdsGraphQlRequest( - // sourceClient, "1489488b-f737-4a9e-ba49-2d42d84c4c6f", "channelKey"); - // - // // test - // final InventoryEntrySyncer inventoryEntrySyncer = - // InventoryEntrySyncer.of(sourceClient, targetClient, mock(Clock.class)); - // inventoryEntrySyncer.sync(null, true).toCompletableFuture().join(); - // - // // assertion - // final LoggingEvent errorLog = syncerTestLogger.getAllLoggingEvents().get(1); - // assertThat(errorLog.getMessage()) - // .isEqualTo( - // "Error when trying to sync inventory entry. Existing key: <>. Update - // actions: []"); - // assertThat(errorLog.getThrowable().get().getMessage()) - // .isEqualTo( - // "InventoryEntryDraft doesn't have a SKU. Please make sure all inventory entry drafts - // have SKUs."); - // } + @Test + void of_ShouldCreateInventoryEntrySyncerInstance() { + // test + final InventoryEntrySyncer inventorySyncer = + InventoryEntrySyncer.of( + mock(ProjectApiRoot.class), mock(ProjectApiRoot.class), getMockedClock()); + + // assertions + assertThat(inventorySyncer).isNotNull(); + assertThat(inventorySyncer.getSync()).isInstanceOf(InventorySync.class); + } + + @Test + void transform_ShouldReplaceInventoryEntryReferenceIdsWithKeys() throws JsonProcessingException { + // preparation + final ProjectApiRoot sourceClient = mock(ProjectApiRoot.class); + final InventoryEntrySyncer inventoryEntrySyncer = + InventoryEntrySyncer.of(sourceClient, mock(ProjectApiRoot.class), getMockedClock()); + final List inventoryPage = + asList( + readObjectFromResource("inventory-sku-1.json", InventoryEntry.class), + readObjectFromResource("inventory-sku-2.json", InventoryEntry.class)); + final List referenceIds = + inventoryPage.stream() + .filter(inventoryEntry -> inventoryEntry.getSupplyChannel() != null) + .filter(inventoryEntry -> inventoryEntry.getCustom() != null) + .flatMap( + inventoryEntry -> + Stream.of( + inventoryEntry.getCustom().getType().getId(), + inventoryEntry.getSupplyChannel().getId())) + .collect(Collectors.toList()); + + final String jsonStringCustomTypes = + "{\"data\":{\"typeDefinitions\":{\"results\":[{\"id\":\"02e915e7-7763-48d1-83bd-d4e940a1a368\"," + + "\"key\":\"test-custom-type-key\"}]}}}"; + final GraphQLResponse customTypesResult = + readObject(jsonStringCustomTypes, GraphQLResponse.class); + + final String jsonStringSupplyChannels = + "{\"data\":{\"channels\":{\"results\":[{\"id\":\"5c0516b5-f506-4b6a-b4d1-c06ca29ab7e1\"," + + "\"key\":\"test-channel-key\"}]}}}"; + final GraphQLResponse supplyChannelsResult = + readObject(jsonStringSupplyChannels, GraphQLResponse.class); + + final ApiHttpResponse graphQLResponse = mock(ApiHttpResponse.class); + + when(graphQLResponse.getBody()).thenReturn(customTypesResult).thenReturn(supplyChannelsResult); + final ByProjectKeyGraphqlRequestBuilder byProjectKeyGraphqlRequestBuilder = mock(); + when(sourceClient.graphql()).thenReturn(byProjectKeyGraphqlRequestBuilder); + final ByProjectKeyGraphqlPost byProjectKeyGraphqlPost = mock(); + when(byProjectKeyGraphqlRequestBuilder.post(any(GraphQLRequest.class))) + .thenReturn(byProjectKeyGraphqlPost); + when(byProjectKeyGraphqlPost.execute()) + .thenReturn(CompletableFuture.completedFuture(graphQLResponse)); + + // test + final CompletionStage> draftsFromPageStage = + inventoryEntrySyncer.transform(inventoryPage); + + // assertions + final List expectedResult = + toInventoryEntryDrafts(sourceClient, referenceIdToKeyCache, inventoryPage).join(); + final List referenceKeys = + expectedResult.stream() + .filter(inventoryEntry -> inventoryEntry.getSupplyChannel() != null) + .filter(inventoryEntry -> inventoryEntry.getCustom() != null) + .flatMap( + inventoryEntry -> + Stream.of( + inventoryEntry.getCustom().getType().getId(), + inventoryEntry.getSupplyChannel().getId())) + .collect(Collectors.toList()); + assertThat(referenceKeys).doesNotContainAnyElementsOf(referenceIds); + assertThat(draftsFromPageStage).isCompletedWithValue(expectedResult); + } + + @Test + @Disabled("https://commercetools.atlassian.net/browse/DEVX-275") + void syncWithError_ShouldCallErrorCallback() { + // preparation: inventory entry with no key is synced + final ProjectApiRoot sourceClient = mock(ProjectApiRoot.class); + final ProjectApiRoot targetClient = mock(ProjectApiRoot.class); + + final List inventoryEntries = + Collections.singletonList( + readObjectFromResource("inventory-no-sku.json", InventoryEntry.class)); + + final ByProjectKeyInventoryRequestBuilder byProjectKeyInventoryRequestBuilder = mock(); + when(sourceClient.inventory()).thenReturn(byProjectKeyInventoryRequestBuilder); + final ByProjectKeyInventoryGet byProjectKeyInventoryGet = mock(); + when(byProjectKeyInventoryRequestBuilder.get()).thenReturn(byProjectKeyInventoryGet); + when(byProjectKeyInventoryGet.withSort(anyString())).thenReturn(byProjectKeyInventoryGet); + when(byProjectKeyInventoryGet.withLimit(anyInt())).thenReturn(byProjectKeyInventoryGet); + when(byProjectKeyInventoryGet.withWithTotal(anyBoolean())).thenReturn(byProjectKeyInventoryGet); + final ApiHttpResponse response = mock(ApiHttpResponse.class); + final InventoryPagedQueryResponse inventoryPagedQueryResponse = + InventoryPagedQueryResponseBuilder.of() + .results(inventoryEntries) + .limit(20L) + .offset(0L) + .count(1L) + .build(); + when(response.getBody()).thenReturn(inventoryPagedQueryResponse); + when(byProjectKeyInventoryGet.execute()) + .thenReturn(CompletableFuture.completedFuture(response)); + + mockResourceIdsGraphQlRequest( + sourceClient, "typeDefinitions", "4db98ea6-38dc-4ccb-b20f-466e1566567h", "customTypeKey"); + mockResourceIdsGraphQlRequest( + sourceClient, "channels", "1489488b-f737-4a9e-ba49-2d42d84c4c6f", "channelKey"); + + // test + final InventoryEntrySyncer inventoryEntrySyncer = + InventoryEntrySyncer.of(sourceClient, targetClient, mock(Clock.class)); + inventoryEntrySyncer.sync(null, true).toCompletableFuture().join(); + + // assertion + final LoggingEvent errorLog = syncerTestLogger.getAllLoggingEvents().get(1); + assertThat(errorLog.getMessage()) + .isEqualTo( + "Error when trying to sync inventory entry. Existing key: <>. Update actions: []"); + assertThat(errorLog.getThrowable().get().getMessage()) + .isEqualTo( + "InventoryEntryDraft doesn't have a SKU. Please make sure all inventory entry drafts have SKUs."); + } } diff --git a/src/test/java/com/commercetools/project/sync/util/TestUtils.java b/src/test/java/com/commercetools/project/sync/util/TestUtils.java index 810fccd2..4c82fe86 100644 --- a/src/test/java/com/commercetools/project/sync/util/TestUtils.java +++ b/src/test/java/com/commercetools/project/sync/util/TestUtils.java @@ -12,6 +12,8 @@ import static org.mockito.Mockito.when; import com.commercetools.api.client.ByProjectKeyCustomObjectsPost; +import com.commercetools.api.client.ByProjectKeyGraphqlPost; +import com.commercetools.api.client.ByProjectKeyGraphqlRequestBuilder; import com.commercetools.api.client.ProjectApiRoot; import com.commercetools.api.defaultconfig.ApiRootBuilder; import com.commercetools.api.models.custom_object.CustomObject; @@ -290,14 +292,28 @@ public static Clock getMockedClock() { return clock; } - public static void mockResourceIdsGraphQlRequest(ProjectApiRoot client, String id, String key) { + public static void mockResourceIdsGraphQlRequest( + ProjectApiRoot client, String resource, String id, String key) { final String jsonResponseString = - "{\"results\":[{\"id\":\"" + id + "\"," + "\"key\":\"" + key + "\"}]}"; + "{\"data\":{\"" + + resource + + "\":{\"results\":[{\"id\":\"" + + id + + "\"," + + "\"key\":\"" + + key + + "\"}]}}}"; final GraphQLResponse result = GraphQLResponseBuilder.of().data(jsonResponseString).build(); - final ApiHttpResponse apiHttpResponse = mock(ApiHttpResponse.class); + final ApiHttpResponse apiHttpResponse = mock(ApiHttpResponse.class); + when(apiHttpResponse.getBody()).thenReturn(result); - when(client.graphql().post(any(GraphQLRequest.class)).execute()) + final ByProjectKeyGraphqlRequestBuilder byProjectKeyGraphqlRequestBuilder = mock(); + when(client.graphql()).thenReturn(byProjectKeyGraphqlRequestBuilder); + final ByProjectKeyGraphqlPost byProjectKeyGraphqlPost = mock(); + when(byProjectKeyGraphqlRequestBuilder.post(any(GraphQLRequest.class))) + .thenReturn(byProjectKeyGraphqlPost); + when(byProjectKeyGraphqlPost.execute()) .thenReturn(CompletableFuture.completedFuture(apiHttpResponse)); } From 9bcfbbb5c19a582e3fcead5756b0c641abedc2cc Mon Sep 17 00:00:00 2001 From: lojzatran Date: Fri, 20 Oct 2023 16:48:25 +0200 Subject: [PATCH 12/14] DEVX-248 refactor category syncer test --- .../sync/category/CategorySyncerTest.java | 39 ++----------------- .../InventoryEntrySyncerTest.java | 2 +- .../project/sync/util/TestUtils.java | 6 +-- 3 files changed, 8 insertions(+), 39 deletions(-) diff --git a/src/test/java/com/commercetools/project/sync/category/CategorySyncerTest.java b/src/test/java/com/commercetools/project/sync/category/CategorySyncerTest.java index d10f2c50..5e63a65e 100644 --- a/src/test/java/com/commercetools/project/sync/category/CategorySyncerTest.java +++ b/src/test/java/com/commercetools/project/sync/category/CategorySyncerTest.java @@ -13,15 +13,11 @@ import com.commercetools.api.client.ByProjectKeyCategoriesKeyByKeyGet; import com.commercetools.api.client.ByProjectKeyCategoriesKeyByKeyRequestBuilder; import com.commercetools.api.client.ByProjectKeyCategoriesRequestBuilder; -import com.commercetools.api.client.ByProjectKeyGraphqlPost; -import com.commercetools.api.client.ByProjectKeyGraphqlRequestBuilder; import com.commercetools.api.client.ProjectApiRoot; import com.commercetools.api.models.category.Category; import com.commercetools.api.models.category.CategoryDraft; import com.commercetools.api.models.category.CategoryPagedQueryResponse; import com.commercetools.api.models.category.CategoryPagedQueryResponseBuilder; -import com.commercetools.api.models.graph_ql.GraphQLRequest; -import com.commercetools.api.models.graph_ql.GraphQLResponse; import com.commercetools.sync.categories.CategorySync; import com.commercetools.sync.commons.utils.CaffeineReferenceIdToKeyCacheImpl; import com.commercetools.sync.commons.utils.ReferenceIdToKeyCache; @@ -83,21 +79,8 @@ void transform_ShouldReplaceCategoryReferenceIdsWithKeys() throws JsonProcessing .map(category -> category.getCustom().getType().getId()) .collect(Collectors.toList()); - final String jsonStringCustomTypes = - "{\"data\":{\"typeDefinitions\":{\"results\":[{\"id\":\"53c4a8b4-754f-4b95-b6f2-3e1e70e3d0c3\",\"key\":\"cat1\"}]}}}"; - - final GraphQLResponse customTypesResult = - readObject(jsonStringCustomTypes, GraphQLResponse.class); - - final ApiHttpResponse response = mock(ApiHttpResponse.class); - when(response.getBody()).thenReturn(customTypesResult); - - final ByProjectKeyGraphqlRequestBuilder byProjectKeyGraphqlRequestBuilder = mock(); - when(sourceClient.graphql()).thenReturn(byProjectKeyGraphqlRequestBuilder); - final ByProjectKeyGraphqlPost byProjectKeyGraphqlPost = mock(); - when(byProjectKeyGraphqlRequestBuilder.post(any(GraphQLRequest.class))) - .thenReturn(byProjectKeyGraphqlPost); - when(byProjectKeyGraphqlPost.execute()).thenReturn(CompletableFuture.completedFuture(response)); + mockResourceIdsGraphQlRequest( + sourceClient, "typeDefinitions", "53c4a8b4-754f-4b95-b6f2-3e1e70e3d0c3", "cat1"); // test final CompletionStage> draftsFromPageStage = @@ -229,22 +212,8 @@ void syncWithWarning_ShouldCallWarningCallback() throws JsonProcessingException when(byProjectKeyCategoriesGetTarget.execute()) .thenReturn(CompletableFuture.completedFuture(targetResponse)); - final String jsonStringCustomTypes = - "{\"data\":{\"categories\":{\"results\":[{\"id\":\"ba81a6da-cf83-435b-a89e-2afab579846f\",\"key\":\"categoryKey2\"}]}}}"; - - final GraphQLResponse customTypesResult = - readObject(jsonStringCustomTypes, GraphQLResponse.class); - - final ApiHttpResponse graphQLResponse = mock(ApiHttpResponse.class); - when(graphQLResponse.getBody()).thenReturn(customTypesResult); - - final ByProjectKeyGraphqlRequestBuilder byProjectKeyGraphqlRequestBuilder = mock(); - when(targetClient.graphql()).thenReturn(byProjectKeyGraphqlRequestBuilder); - final ByProjectKeyGraphqlPost byProjectKeyGraphqlPost = mock(); - when(byProjectKeyGraphqlRequestBuilder.post(any(GraphQLRequest.class))) - .thenReturn(byProjectKeyGraphqlPost); - when(byProjectKeyGraphqlPost.execute()) - .thenReturn(CompletableFuture.completedFuture(graphQLResponse)); + mockResourceIdsGraphQlRequest( + targetClient, "categories", "ba81a6da-cf83-435b-a89e-2afab579846f", "categoryKey2"); // test final CategorySyncer categorySyncer = diff --git a/src/test/java/com/commercetools/project/sync/inventoryentry/InventoryEntrySyncerTest.java b/src/test/java/com/commercetools/project/sync/inventoryentry/InventoryEntrySyncerTest.java index 4f903432..ee831181 100644 --- a/src/test/java/com/commercetools/project/sync/inventoryentry/InventoryEntrySyncerTest.java +++ b/src/test/java/com/commercetools/project/sync/inventoryentry/InventoryEntrySyncerTest.java @@ -130,7 +130,7 @@ void transform_ShouldReplaceInventoryEntryReferenceIdsWithKeys() throws JsonProc @Test @Disabled("https://commercetools.atlassian.net/browse/DEVX-275") - void syncWithError_ShouldCallErrorCallback() { + void syncWithError_ShouldCallErrorCallback() throws JsonProcessingException { // preparation: inventory entry with no key is synced final ProjectApiRoot sourceClient = mock(ProjectApiRoot.class); final ProjectApiRoot targetClient = mock(ProjectApiRoot.class); diff --git a/src/test/java/com/commercetools/project/sync/util/TestUtils.java b/src/test/java/com/commercetools/project/sync/util/TestUtils.java index 4c82fe86..9ad97673 100644 --- a/src/test/java/com/commercetools/project/sync/util/TestUtils.java +++ b/src/test/java/com/commercetools/project/sync/util/TestUtils.java @@ -22,7 +22,6 @@ import com.commercetools.api.models.error.ErrorResponseBuilder; import com.commercetools.api.models.graph_ql.GraphQLRequest; import com.commercetools.api.models.graph_ql.GraphQLResponse; -import com.commercetools.api.models.graph_ql.GraphQLResponseBuilder; import com.commercetools.project.sync.model.response.LastSyncCustomObject; import com.commercetools.sync.products.helpers.ProductSyncStatistics; import com.fasterxml.jackson.core.JsonProcessingException; @@ -293,7 +292,8 @@ public static Clock getMockedClock() { } public static void mockResourceIdsGraphQlRequest( - ProjectApiRoot client, String resource, String id, String key) { + ProjectApiRoot client, String resource, String id, String key) + throws JsonProcessingException { final String jsonResponseString = "{\"data\":{\"" + resource @@ -303,7 +303,7 @@ public static void mockResourceIdsGraphQlRequest( + "\"key\":\"" + key + "\"}]}}}"; - final GraphQLResponse result = GraphQLResponseBuilder.of().data(jsonResponseString).build(); + final GraphQLResponse result = readObject(jsonResponseString, GraphQLResponse.class); final ApiHttpResponse apiHttpResponse = mock(ApiHttpResponse.class); From 5af3241a67c14c3907c3c94bf08c1dbbde471fea Mon Sep 17 00:00:00 2001 From: lojzatran Date: Mon, 23 Oct 2023 21:33:32 +0200 Subject: [PATCH 13/14] DEVX-248 refactor code --- .../java/com/commercetools/project/sync/util/TestUtils.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/test/java/com/commercetools/project/sync/util/TestUtils.java b/src/test/java/com/commercetools/project/sync/util/TestUtils.java index 9ad97673..18e4c1b6 100644 --- a/src/test/java/com/commercetools/project/sync/util/TestUtils.java +++ b/src/test/java/com/commercetools/project/sync/util/TestUtils.java @@ -292,8 +292,7 @@ public static Clock getMockedClock() { } public static void mockResourceIdsGraphQlRequest( - ProjectApiRoot client, String resource, String id, String key) - throws JsonProcessingException { + ProjectApiRoot client, String resource, String id, String key) { final String jsonResponseString = "{\"data\":{\"" + resource @@ -303,7 +302,7 @@ public static void mockResourceIdsGraphQlRequest( + "\"key\":\"" + key + "\"}]}}}"; - final GraphQLResponse result = readObject(jsonResponseString, GraphQLResponse.class); + final GraphQLResponse result = JsonUtils.fromJsonString(jsonResponseString, GraphQLResponse.class); final ApiHttpResponse apiHttpResponse = mock(ApiHttpResponse.class); From 2f31ff3a72483400da8c32da499a91529575dde5 Mon Sep 17 00:00:00 2001 From: lojzatran Date: Mon, 23 Oct 2023 21:34:40 +0200 Subject: [PATCH 14/14] DEVX-248 fix formatting --- .../java/com/commercetools/project/sync/util/TestUtils.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/commercetools/project/sync/util/TestUtils.java b/src/test/java/com/commercetools/project/sync/util/TestUtils.java index 18e4c1b6..9b174d07 100644 --- a/src/test/java/com/commercetools/project/sync/util/TestUtils.java +++ b/src/test/java/com/commercetools/project/sync/util/TestUtils.java @@ -302,7 +302,8 @@ public static void mockResourceIdsGraphQlRequest( + "\"key\":\"" + key + "\"}]}}}"; - final GraphQLResponse result = JsonUtils.fromJsonString(jsonResponseString, GraphQLResponse.class); + final GraphQLResponse result = + JsonUtils.fromJsonString(jsonResponseString, GraphQLResponse.class); final ApiHttpResponse apiHttpResponse = mock(ApiHttpResponse.class);