diff --git a/Apps/W1/Shopify/test/Products/ShpfyCreateItemAsVariantSub.Codeunit.al b/Apps/W1/Shopify/test/Products/ShpfyCreateItemAsVariantSub.Codeunit.al new file mode 100644 index 0000000000..9c65bbc8c5 --- /dev/null +++ b/Apps/W1/Shopify/test/Products/ShpfyCreateItemAsVariantSub.Codeunit.al @@ -0,0 +1,134 @@ +codeunit 139620 "Shpfy CreateItemAsVariantSub" +{ + EventSubscriberInstance = Manual; + + var + GraphQueryTxt: Text; + NewVariantId: BigInteger; + DefaultVariantId: BigInteger; + MultipleOptions: Boolean; + + [EventSubscriber(ObjectType::Codeunit, Codeunit::"Shpfy Communication Events", 'OnClientSend', '', true, false)] + local procedure OnClientSend(HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage) + begin + MakeResponse(HttpRequestMessage, HttpResponseMessage); + end; + + [EventSubscriber(ObjectType::Codeunit, Codeunit::"Shpfy Communication Events", 'OnGetContent', '', true, false)] + local procedure OnGetContent(HttpResponseMessage: HttpResponseMessage; var Response: Text) + begin + HttpResponseMessage.Content.ReadAs(Response); + end; + + local procedure MakeResponse(HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage) + var + Uri: Text; + GraphQlQuery: Text; + CreateItemVariantTok: Label '{"query":"mutation { productVariantCreate(input: {productId: \"gid://shopify/Product/', locked = true; + GetOptionsStartTok: Label '{"query":"{product(id: \"gid://shopify/Product/', locked = true; + GetOptionsEndTok: Label '\") {id title options {id name}}}"}', Locked = true; + RemoveVariantStartTok: Label '{"query":"mutation {productVariantDelete(id: \"gid://shopify/ProductVariant/', Locked = true; + RemoveVariantEndTok: Label '\") {deletedProductVariantId userErrors{field message}}}"}', Locked = true; + GetVariantsTok: Label 'variants(first:200){pageInfo{hasNextPage} edges{cursor node{legacyResourceId updatedAt}}}', Locked = true; + + GraphQLCmdTxt: Label '/graphql.json', Locked = true; + begin + case HttpRequestMessage.Method of + 'POST': + begin + Uri := HttpRequestMessage.GetRequestUri(); + if Uri.EndsWith(GraphQLCmdTxt) then + if HttpRequestMessage.Content.ReadAs(GraphQlQuery) then + case true of + GraphQlQuery.StartsWith(CreateItemVariantTok): + HttpResponseMessage := GetCreatedVariantResponse(); + GraphQlQuery.StartsWith(GetOptionsStartTok) and GraphQlQuery.EndsWith(GetOptionsEndTok): + if MultipleOptions then + HttpResponseMessage := GetProductMultipleOptionsResponse() + else + HttpResponseMessage := GetProductOptionsResponse(); + GraphQlQuery.StartsWith(RemoveVariantStartTok) and GraphQlQuery.EndsWith(RemoveVariantEndTok): + begin + HttpResponseMessage := GetRemoveVariantResponse(); + GraphQueryTxt := GraphQlQuery; + end; + GraphQlQuery.Contains(GetVariantsTok): + HttpResponseMessage := GetDefaultVariantResponse(); + end; + end; + end; + end; + + local procedure GetCreatedVariantResponse(): HttpResponseMessage; + var + Any: Codeunit Any; + HttpResponseMessage: HttpResponseMessage; + BodyTxt: Text; + begin + Any.SetDefaultSeed(); + NewVariantId := Any.IntegerInRange(100000, 999999); + BodyTxt := StrSubstNo('{ "data": { "productVariantCreate": { "legacyResourceId": %1 } } }', NewVariantId); + HttpResponseMessage.Content.WriteFrom(BodyTxt); + exit(HttpResponseMessage); + end; + + local procedure GetProductOptionsResponse(): HttpResponseMessage + var + HttpResponseMessage: HttpResponseMessage; + BodyTxt: Text; + begin + BodyTxt := '{"data": {"product": {"id": "gid://shopify/Product/123456", "title": "Product 1", "options": [{"id": "gid://shopify/ProductOption/1", "name": "Option 1"}]}}}'; + HttpResponseMessage.Content.WriteFrom(BodyTxt); + exit(HttpResponseMessage); + end; + + local procedure GetRemoveVariantResponse(): HttpResponseMessage + var + HttpResponseMessage: HttpResponseMessage; + BodyTxt: Text; + begin + BodyTxt := '{}'; + HttpResponseMessage.Content.WriteFrom(BodyTxt); + exit(HttpResponseMessage); + end; + + local procedure GetProductMultipleOptionsResponse(): HttpResponseMessage + var + HttpResponseMessage: HttpResponseMessage; + BodyTxt: Text; + begin + BodyTxt := '{"data": {"product": {"id": "gid://shopify/Product/123456", "title": "Product 1", "options": [{"id": "gid://shopify/ProductOption/1", "name": "Option 1"}, {"id": "gid://shopify/ProductOption/2", "name": "Option 2"}]}}}'; + HttpResponseMessage.Content.WriteFrom(BodyTxt); + exit(HttpResponseMessage); + end; + + local procedure GetDefaultVariantResponse(): HttpResponseMessage + var + HttpResponseMessage: HttpResponseMessage; + BodyTxt: Text; + begin + BodyTxt := StrSubstNo('{ "data" : { "product" : { "variants" : { "edges" : [ { "node" : { "legacyResourceId" : %1 } } ] } } } }', DefaultVariantId); + HttpResponseMessage.Content.WriteFrom(BodyTxt); + exit(HttpResponseMessage); + end; + + procedure GetNewVariantId(): BigInteger + begin + exit(NewVariantId); + end; + + procedure GetGraphQueryTxt(): Text + begin + exit(GraphQueryTxt); + end; + + procedure SetMultipleOptions(NewMultipleOptions: Boolean) + begin + this.MultipleOptions := NewMultipleOptions; + end; + + procedure SetDefaultVariantId(NewDefaultVariantId: BigInteger) + begin + this.DefaultVariantId := NewDefaultVariantId; + end; +} \ No newline at end of file diff --git a/Apps/W1/Shopify/test/Products/ShpfyCreateItemVariantTest.Codeunit.al b/Apps/W1/Shopify/test/Products/ShpfyCreateItemVariantTest.Codeunit.al new file mode 100644 index 0000000000..77761494a0 --- /dev/null +++ b/Apps/W1/Shopify/test/Products/ShpfyCreateItemVariantTest.Codeunit.al @@ -0,0 +1,206 @@ +codeunit 139619 "Shpfy Create Item Variant Test" +{ + Subtype = Test; + TestPermissions = Disabled; + + var + Shop: Record "Shpfy Shop"; + Any: Codeunit Any; + LibraryAssert: Codeunit "Library Assert"; + ShpfyInitializeTest: Codeunit "Shpfy Initialize Test"; + IsInitialized: Boolean; + + trigger OnRun() + begin + IsInitialized := false; + end; + + [Test] + procedure UnitTestCreateVariantFromItem() + var + Item: Record "Item"; + ShpfyVariant: Record "Shpfy Variant"; + ShpfyProduct: Record "Shpfy Product"; + ShpfyProductInitTest: Codeunit "Shpfy Product Init Test"; + CreateItemAsVariant: Codeunit "Shpfy Create Item As Variant"; + CreateItemAsVariantSub: Codeunit "Shpfy CreateItemAsVariantSub"; + ParentProductId: BigInteger; + VariantId: BigInteger; + begin + // [SCENARIO] Create a variant from a given item + Initialize(); + + // [GIVEN] Item + Item := ShpfyProductInitTest.CreateItem(Shop."Item Templ. Code", Any.DecimalInRange(10, 100, 2), Any.DecimalInRange(100, 500, 2)); + // [GIVEN] Shopify product + ParentProductId := CreateShopifyProduct(Item.SystemId); + + // [WHEN] Invoke CreateItemAsVariant.CreateVariantFromItem + BindSubscription(CreateItemAsVariantSub); + CreateItemAsVariant.SetParentProduct(ParentProductId); + CreateItemAsVariant.CreateVariantFromItem(Item); + VariantId := CreateItemAsVariantSub.GetNewVariantId(); + UnbindSubscription(CreateItemAsVariantSub); + + // [THEN] Variant is created + LibraryAssert.IsTrue(ShpfyVariant.Get(VariantId), 'Variant not created'); + LibraryAssert.AreEqual(Item."No.", ShpfyVariant.Title, 'Title not set'); + LibraryAssert.AreEqual(Item."No.", ShpfyVariant."Option 1 Value", 'Option 1 Value not set'); + LibraryAssert.AreEqual('Variant', ShpfyVariant."Option 1 Name", 'Option 1 Name not set'); + LibraryAssert.AreEqual(ParentProductId, ShpfyVariant."Product Id", 'Parent product not set'); + LibraryAssert.IsTrue(ShpfyProduct.Get(ParentProductId), 'Parent product not found'); + LibraryAssert.IsTrue(ShpfyProduct."Has Variants", 'Has Variants not set'); + end; + + [Test] + procedure UnitTestGetProductOptions() + var + Item: Record "Item"; + ShpfyProductInitTest: Codeunit "Shpfy Product Init Test"; + ProductAPI: Codeunit "Shpfy Product API"; + CreateItemAsVariantSub: Codeunit "Shpfy CreateItemAsVariantSub"; + ProductId: BigInteger; + Options: Dictionary of [Text, Text]; + begin + // [SCENARIO] Get product options for a given shopify product + Initialize(); + + // [GIVEN] Item + Item := ShpfyProductInitTest.CreateItem(Shop."Item Templ. Code", Any.DecimalInRange(10, 100, 2), Any.DecimalInRange(100, 500, 2)); + // [GIVEN] Shopify product + ProductId := Any.IntegerInRange(10000, 99999); + + // [WHEN] Invoke ProductAPI.GetProductOptions + BindSubscription(CreateItemAsVariantSub); + Options := ProductAPI.GetProductOptions(ProductId); + UnbindSubscription(CreateItemAsVariantSub); + + // [THEN] Options are returned + LibraryAssert.AreEqual(1, Options.Count(), 'Options not returned'); + end; + + [Test] + procedure UnitTestDeleteProductVariant() + var + CreateItemAsVariantSub: Codeunit "Shpfy CreateItemAsVariantSub"; + VariantAPI: Codeunit "Shpfy Variant API"; + VariantId: BigInteger; + ActualQueryTxt: Text; + begin + // [SCENARIO] Delete a product variant + Initialize(); + + // [GIVEN] Shopify Variant Id + VariantId := Any.IntegerInRange(10000, 99999); + + // [WHEN] Invoke ProductAPI.DeleteProductVariant + BindSubscription(CreateItemAsVariantSub); + VariantAPI.DeleteProductVariant(VariantId); + ActualQueryTxt := CreateItemAsVariantSub.GetGraphQueryTxt(); + UnbindSubscription(CreateItemAsVariantSub); + + // [THEN] Query is correct + LibraryAssert.IsTrue(ActualQueryTxt.Contains('{"query":"mutation {productVariantDelete('), 'Query not correct'); + LibraryAssert.IsTrue(ActualQueryTxt.Contains(StrSubstNo('id: \"gid://shopify/ProductVariant/%1\"', VariantId)), 'Variant Id not set'); + end; + + [Test] + procedure UnitTestCreateVariantFromProductWithMultipleOptions() + var + Item: Record "Item"; + ShpfyProductInitTest: Codeunit "Shpfy Product Init Test"; + CreateItemAsVariant: Codeunit "Shpfy Create Item As Variant"; + CreateItemAsVariantSub: Codeunit "Shpfy CreateItemAsVariantSub"; + ProductId: BigInteger; + begin + // [SCENARIO] Create a variant from a product with multiple options + Initialize(); + + // [GIVEN] Item + Item := ShpfyProductInitTest.CreateItem(Shop."Item Templ. Code", Any.DecimalInRange(10, 100, 2), Any.DecimalInRange(100, 500, 2)); + // [GIVEN] Shopify product + ProductId := CreateShopifyProduct(Item.SystemId); + + // [GIVEN] Multiple options for the product in Shopify + CreateItemAsVariantSub.SetMultipleOptions(true); + + // [WHEN] Invoke ProductAPI.CheckProductAndShopSettings + BindSubscription(CreateItemAsVariantSub); + CreateItemAsVariant.SetParentProduct(ProductId); + asserterror CreateItemAsVariant.CheckProductAndShopSettings(); + UnbindSubscription(CreateItemAsVariantSub); + + // [THEN] Error is thrown + LibraryAssert.ExpectedError('The product has more than one option. Items cannot be added as variants to a product with multiple options.'); + end; + + [Test] + procedure UnitTestRemoveDefaultVariantTest() + var + Item: Record Item; + ShpfyVariant: Record "Shpfy Variant"; + ShpfyProductInitTest: Codeunit "Shpfy Product Init Test"; + CreateItemAsVariant: Codeunit "Shpfy Create Item As Variant"; + CreateItemAsVariantSub: Codeunit "Shpfy CreateItemAsVariantSub"; + ProductId, VariantId : BigInteger; + begin + // [SCENARIO] Remove default variant + Initialize(); + + // [GIVEN] Item + Item := ShpfyProductInitTest.CreateItem(Shop."Item Templ. Code", Any.DecimalInRange(10, 100, 2), Any.DecimalInRange(100, 500, 2)); + // [GIVEN] Shopify product + ProductId := CreateShopifyProduct(Item.SystemId); + // [GIVEN] Shopify variant + VariantId := CreateShopifyVariant(ProductId); + // [GIVEN] Default variant exists in Shopify + CreateItemAsVariantSub.SetDefaultVariantId(VariantId); + + // [WHEN] Invoke CreateItemAsVariant.RemoveDefaultVariant + BindSubscription(CreateItemAsVariantSub); + CreateItemAsVariant.SetParentProduct(ProductId); + CreateItemAsVariant.FindDefaultVariantId(); + CreateItemAsVariant.CreateVariantFromItem(Item); + CreateItemAsVariant.RemoveDefaultVariant(); + UnbindSubscription(CreateItemAsVariantSub); + + // [THEN] Default variant is removed + ShpfyVariant.SetRange(Id, VariantId); + LibraryAssert.IsTrue(ShpfyVariant.IsEmpty(), 'Default variant not removed'); + + end; + + local procedure Initialize() + begin + Any.SetDefaultSeed(); + if IsInitialized then + exit; + Shop := ShpfyInitializeTest.CreateShop(); + Commit(); + IsInitialized := true; + end; + + local procedure CreateShopifyProduct(SystemId: Guid): BigInteger + var + ShopifyProduct: Record "Shpfy Product"; + begin + ShopifyProduct.Init(); + ShopifyProduct.Id := Any.IntegerInRange(10000, 99999); + ShopifyProduct."Shop Code" := Shop."Code"; + ShopifyProduct."Item SystemId" := SystemId; + ShopifyProduct.Insert(true); + exit(ShopifyProduct."Id"); + end; + + local procedure CreateShopifyVariant(ProductId: BigInteger): BigInteger + var + ShpfyVariant: Record "Shpfy Variant"; + begin + ShpfyVariant.Init(); + ShpfyVariant.Id := Any.IntegerInRange(10000, 99999); + ShpfyVariant."Shop Code" := Shop."Code"; + ShpfyVariant."Product Id" := ProductId; + ShpfyVariant.Insert(false); + exit(ShpfyVariant."Id"); + end; +}