public async Task RetrievingContentModelWithItemInlineReferencingItselfDoesNotCycle() { var typeProvider = A.Fake <ITypeProvider>(); var contentLinkUrlResolver = A.Fake <IContentLinkUrlResolver>(); var propertyMapper = A.Fake <IPropertyMapper>(); A.CallTo(() => typeProvider.GetType(A <string> ._)).Returns(typeof(ContentItemWithSingleRte)); A.CallTo(() => propertyMapper.IsMatch(A <PropertyInfo> ._, A <string> ._, A <string> ._)).Returns(true); var processor = InlineContentItemsProcessorFactory .WithResolver(ResolveItemWithSingleRte) .Build(); var retriever = new ModelProvider(contentLinkUrlResolver, processor, typeProvider, propertyMapper, new DeliveryJsonSerializer(), new HtmlParser()); var item = JToken.FromObject(Rt3); var linkedItems = JToken.FromObject(LinkedItemsForItemReferencingItself); var result = await retriever.GetContentItemModelAsync <ContentItemWithSingleRte>(item, linkedItems); Assert.Equal("<span>RT</span><span>RT</span>", result.Rt); Assert.IsType <ContentItemWithSingleRte>(result); }
public void NestedInlineContentItemIsProcessedByValueProcessor() { var insertedContentName = "dummyCodename1"; string wrapperWithObject = WrapElementWithDivs(GetContentItemObjectElement(insertedContentName)); const string insertedContentItemValue = "dummyValue"; var plainHtml = $"<p>Lorem ipsum etc..<a>asdf</a>..</p>"; var input = plainHtml + wrapperWithObject; var processedContentItems = new Dictionary <string, object> { { insertedContentName, new DummyItem { Value = insertedContentItemValue } } }; var inlineContentItemsProcessor = InlineContentItemsProcessorFactory .WithResolver(factory => factory.ResolveTo <DummyItem>(item => item.Value ?? string.Empty)) .Build(); var result = inlineContentItemsProcessor.Process(input, processedContentItems); Assert.Equal(plainHtml + WrapElementWithDivs(insertedContentItemValue), result); }
public async void ResolveLinksInStronglyTypedModel() { var mockHttp = new MockHttpMessageHandler(); string guid = Guid.NewGuid().ToString(); string url = $"https://deliver.kontent.ai/{guid}/items/coffee_processing_techniques"; mockHttp.When(url). Respond("application/json", File.ReadAllText(Path.Combine(Environment.CurrentDirectory, $"Fixtures{Path.DirectorySeparatorChar}ContentLinkResolver{Path.DirectorySeparatorChar}coffee_processing_techniques.json"))); var deliveryOptions = DeliveryOptionsFactory.CreateMonitor(new DeliveryOptions { ProjectId = guid }); var options = DeliveryOptionsFactory.Create(new DeliveryOptions { ProjectId = guid }); var deliveryHttpClient = new DeliveryHttpClient(mockHttp.ToHttpClient()); var resiliencePolicyProvider = new DefaultRetryPolicyProvider(options); var contentLinkUrlResolver = new CustomContentLinkUrlResolver(); var contentLinkResolver = new ContentLinkResolver(contentLinkUrlResolver); var contentItemsProcessor = InlineContentItemsProcessorFactory.Create(); var modelProvider = new ModelProvider(contentLinkResolver, contentItemsProcessor, new CustomTypeProvider(), new PropertyMapper()); var client = new DeliveryClient( deliveryOptions, contentLinkResolver, contentItemsProcessor, modelProvider, resiliencePolicyProvider, null, null, deliveryHttpClient ); string expected = "Check out our <a data-item-id=\"0c9a11bb-6fc3-409c-b3cb-f0b797e15489\" href=\"http://example.org/brazil-natural-barra-grande\">Brazil Natural Barra Grande</a> coffee for a tasty example."; var item = await client.GetItemAsync <Article>("coffee_processing_techniques"); Assert.Contains(expected, item.Item.BodyCopy); }
public void NestedInlineContentItemIsProcessedByElementProcessor() { var insertedContentName = "dummyCodename1"; var wrapperWithObject = WrapElementWithDivs(GetContentItemObjectElement(insertedContentName)); var plainHtml = $"<p>Lorem ipsum etc..<a>asdf</a>..</p>"; var input = plainHtml + wrapperWithObject; const string insertedContentItemValue = "dummyValue"; var processedContentItems = new Dictionary <string, object> { { insertedContentName, new DummyItem { Value = insertedContentItemValue } } }; var inlineContentItemsProcessor = InlineContentItemsProcessorFactory .WithResolver(ResolveDummyItemToSpan) .Build(); var result = inlineContentItemsProcessor.Process(input, processedContentItems); var expectedElement = $"<span>{insertedContentItemValue}</span>"; Assert.Equal(plainHtml + WrapElementWithDivs(expectedElement), result); }
public void ResolverReturningMixedElementsAndTextIsProcessedCorrectly() { const string insertedContentName = "dummyCodename1"; var wrapperWithObject = GetContentItemObjectElement(insertedContentName); var inputHtml = $"A hyper-hybrid socialization & turbocharges adaptive {wrapperWithObject} frameworks by thinking outside of the box, while the support structures influence the mediators."; const string insertedContentItemValue = "dummyValue"; var processedContentItems = new Dictionary <string, object> { { insertedContentName, new DummyItem { Value = insertedContentItemValue } } }; var inlineContentItemsProcessor = InlineContentItemsProcessorFactory .WithResolver(factory => factory.ResolveTo <DummyItem>(item => $"Text text brackets ( < [ <span>{item.Value}</span><div></div>& Some more text")) .Build(); var result = inlineContentItemsProcessor.Process(inputHtml, processedContentItems); var expectedResults = $"A hyper-hybrid socialization & turbocharges adaptive Text text brackets ( < [ <span>{insertedContentItemValue}</span><div></div>& Some more text frameworks by thinking outside of the box, while the support structures influence the mediators."; Assert.Equal(expectedResults, result); }
public void RetrievingNonExistentContentModelCreatesWarningInRichtext() { var typeProvider = A.Fake <ITypeProvider>(); var contentLinkUrlResolver = A.Fake <IContentLinkUrlResolver>(); var propertyMapper = A.Fake <IPropertyMapper>(); A.CallTo(() => typeProvider.GetType(A <string> ._)).Returns(null); A.CallTo(() => propertyMapper.IsMatch(A <PropertyInfo> ._, A <string> ._, A <string> ._)).Returns(true); var processor = InlineContentItemsProcessorFactory .WithResolver(factory => factory.ResolveTo <UnknownContentItem>(unknownItem => $"Content type '{unknownItem.Type}' has no corresponding model.")) .Build(); var retriever = new ModelProvider(new ContentLinkResolver(contentLinkUrlResolver), processor, typeProvider, propertyMapper); var item = JToken.FromObject(Rt5); var linkedItems = JToken.FromObject(LinkedItemWithNoModel); var expectedResult = $"<span>RT</span>Content type '{linkedItems.SelectToken("linkedItemWithNoModel.system.type")}' has no corresponding model."; var result = retriever.GetContentItemModel <ContentItemWithSingleRte>(item, linkedItems); Assert.Equal(expectedResult, result.Rt); Assert.IsType <ContentItemWithSingleRte>(result); }
public void ContentItemWithMultipleResolversIsHandledByLastResolver() { const string insertedItemName = "dummyItem"; const string insertedImageName = "dummyImage"; var wrapperWithItem = WrapElementWithDivs(GetContentItemObjectElement(insertedItemName)); var wrapperWithImage = WrapElementWithDivs(GetContentItemObjectElement(insertedImageName)); var plainHtml = "<p>Lorem ipsum etc..<a>asdf</a>..</p>"; var input = wrapperWithImage + plainHtml + wrapperWithItem; var processedContentItems = new Dictionary <string, object> { { insertedItemName, new DummyItem() }, { insertedImageName, new DummyImageItem() } }; var inlineContentItemsProcessor = InlineContentItemsProcessorFactory .WithResolver(factory => factory.ResolveByDefaultToMessage("this should not appear for a loosely resolved item")) .AndResolver(factory => factory.ResolveByDefaultToType()) .AndResolver(factory => factory.ResolveToMessage <DummyImageItem>("this should not appear a strongly resolved item")) .AndResolver(factory => factory.ResolveToType <DummyImageItem>()) .Build(); var result = inlineContentItemsProcessor.Process(input, processedContentItems); Assert.Equal($"<div>{typeof(DummyImageItem)}</div>" + plainHtml + $"<div>{typeof(DummyItem)}</div>", result); }
public void DifferentContentTypesUnretrievedAndContentTypesWithoutResolverAreResolvedCorrectly() { const string insertedImage1CodeName = "image1"; const string insertedImage1Source = "www.images.com/image1.png"; const string insertedImage2CodeName = "image2"; const string insertedDummyItem1CodeName = "item1"; const string insertedDummyItem1Value = "Leadership!"; const string insertedDummyItem2CodeName = "item2"; const string insertedDummyItem3CodeName = "item3"; const string insertedDummyItem3Value = "Unity!"; const string unretrievedItemMessage = "Unretrieved item detected!"; const string defaultResolverMessage = "Type witout resolver detected!"; var insertedImage1 = WrapElementWithDivs(GetContentItemObjectElement(insertedImage1CodeName)); var insertedImage2 = GetContentItemObjectElement(insertedImage2CodeName); var insertedDummyItem1 = GetContentItemObjectElement(insertedDummyItem1CodeName); var insertedDummyItem2 = WrapElementWithDivs(GetContentItemObjectElement(insertedDummyItem2CodeName)); var insertedDummyItem3 = GetContentItemObjectElement(insertedDummyItem3CodeName); var htmlInput = $"Opting out of business line is not a choice. {insertedDummyItem2} A radical, unified, highly-curated and" + $" digitized realignment transfers a touchpoint. As a result, the attackers empower our well-planned" + $" brainstorming spaces. It's not about our evidence-based customer centricity. It's about brandings. {insertedImage1}" + $" The project leader swiftly enhances market practices in the core. In the same time, an elite, siloed," + $" breakthrough generates our value-added cross fertilization.\n" + $"Our pre-plan prioritizes the group.Our top-level, service - oriented, ingenuity leverages knowledge" + $" - based commitments.{insertedDummyItem3} The market thinker dramatically enforces our hands" + $" - on brainstorming spaces.Adaptability and skillset invigorate the game changers. {insertedDummyItem1}" + $" The thought leaders target a teamwork-oriented silo.\n" + $"A documented high quality enables our unique, outside -in and customer-centric tailwinds." + $"It's not about our targets. {insertedImage2} It's about infrastructures."; var expectedOutput = $"Opting out of business line is not a choice. <div>{unretrievedItemMessage}</div> A radical, unified, highly-curated and" + $" digitized realignment transfers a touchpoint. As a result, the attackers empower our well-planned" + $" brainstorming spaces. It's not about our evidence-based customer centricity. It's about brandings. <div>{defaultResolverMessage}</div>" + $" The project leader swiftly enhances market practices in the core. In the same time, an elite, siloed," + $" breakthrough generates our value-added cross fertilization.\n" + $"Our pre-plan prioritizes the group.Our top-level, service - oriented, ingenuity leverages knowledge" + $" - based commitments.<span>{insertedDummyItem3Value}</span> The market thinker dramatically enforces our hands" + $" - on brainstorming spaces.Adaptability and skillset invigorate the game changers. <span>{insertedDummyItem1Value}</span>" + $" The thought leaders target a teamwork-oriented silo.\n" + $"A documented high quality enables our unique, outside -in and customer-centric tailwinds." + $"It's not about our targets. {unretrievedItemMessage} It's about infrastructures."; var processedContentItems = new Dictionary <string, object> { { insertedImage1CodeName, new DummyImageItem { Source = insertedImage1Source } }, { insertedImage2CodeName, new UnretrievedContentItem() }, { insertedDummyItem1CodeName, new DummyItem { Value = insertedDummyItem1Value } }, { insertedDummyItem2CodeName, new UnretrievedContentItem() }, { insertedDummyItem3CodeName, new DummyItem { Value = insertedDummyItem3Value } }, }; var inlineContentItemsProcessor = InlineContentItemsProcessorFactory .WithResolver(ResolveDummyItemToSpan) .AndResolver(factory => factory.ResolveByDefaultToMessage(defaultResolverMessage)) .AndResolver(factory => factory.ResolveToMessage <UnretrievedContentItem>(unretrievedItemMessage)) .Build(); var result = inlineContentItemsProcessor.Process(htmlInput, processedContentItems); Assert.Equal(expectedOutput, result); }