public void ManyNestedTest()
    {
        var(_, contentType2) = CreateContentTypes();

        // nested many converter returns the proper value clr type IEnumerable<TestModel>, and cache level
        Assert.AreEqual(typeof(IEnumerable <TestElementModel>), contentType2.GetPropertyType("property2").ClrType);
        Assert.AreEqual(PropertyCacheLevel.Element, contentType2.GetPropertyType("property2").CacheLevel);

        var key     = Guid.NewGuid();
        var keyA    = Guid.NewGuid();
        var keyB    = Guid.NewGuid();
        var content = new InternalPublishedContent(contentType2)
        {
            Key        = key,
            Properties = new[]
            {
                new TestPublishedProperty(contentType2.GetPropertyType("property2"), $@"[
                    {{ ""key"": ""{keyA}"", ""propertyN1"": ""foo"", ""ncContentTypeAlias"": ""contentN1"" }},
                    {{ ""key"": ""{keyB}"", ""propertyN1"": ""bar"", ""ncContentTypeAlias"": ""contentN1"" }}
                ]"),
            },
        };
        var value = content.Value(Mock.Of <IPublishedValueFallback>(), "property2");

        // nested many converter returns proper IEnumerable<TestModel> value
        Assert.IsInstanceOf <IEnumerable <IPublishedElement> >(value);
        Assert.IsInstanceOf <IEnumerable <TestElementModel> >(value);
        var valueM = ((IEnumerable <TestElementModel>)value).ToArray();

        Assert.AreEqual("foo", valueM[0].PropValue);
        Assert.AreEqual(keyA, valueM[0].Key);
        Assert.AreEqual("bar", valueM[1].PropValue);
        Assert.AreEqual(keyB, valueM[1].Key);
    }
    public void SingleNestedTest()
    {
        var(contentType1, _) = CreateContentTypes();

        // nested single converter returns the proper value clr type TestModel, and cache level
        Assert.AreEqual(typeof(TestElementModel), contentType1.GetPropertyType("property1").ClrType);
        Assert.AreEqual(PropertyCacheLevel.Element, contentType1.GetPropertyType("property1").CacheLevel);

        var key     = Guid.NewGuid();
        var keyA    = Guid.NewGuid();
        var content = new InternalPublishedContent(contentType1)
        {
            Key        = key,
            Properties = new[]
            {
                new TestPublishedProperty(
                    contentType1.GetPropertyType("property1"), $@"[
                    {{ ""key"": ""{keyA}"", ""propertyN1"": ""foo"", ""ncContentTypeAlias"": ""contentN1"" }}
                ]"),
            },
        };
        var value = content.Value(Mock.Of <IPublishedValueFallback>(), "property1");

        // nested single converter returns proper TestModel value
        Assert.IsInstanceOf <TestElementModel>(value);
        var valueM = (TestElementModel)value;

        Assert.AreEqual("foo", valueM.PropValue);
        Assert.AreEqual(keyA, valueM.Key);
    }
    public void SimpleConverter2Test()
    {
        var cacheMock    = new Mock <IPublishedContentCache>();
        var cacheContent = new Dictionary <int, IPublishedContent>();

        cacheMock.Setup(x => x.GetById(It.IsAny <int>()))
        .Returns <int>(id => cacheContent.TryGetValue(id, out var content) ? content : null);
        var publishedSnapshotMock = new Mock <IPublishedSnapshot>();

        publishedSnapshotMock.Setup(x => x.Content).Returns(cacheMock.Object);
        var publishedSnapshotAccessorMock = new Mock <IPublishedSnapshotAccessor>();
        var localPublishedSnapshot        = publishedSnapshotMock.Object;

        publishedSnapshotAccessorMock.Setup(x => x.TryGetPublishedSnapshot(out localPublishedSnapshot)).Returns(true);
        var publishedSnapshotAccessor = publishedSnapshotAccessorMock.Object;

        var converters = new PropertyValueConverterCollection(() => new IPropertyValueConverter[]
        {
            new SimpleConverter2(publishedSnapshotAccessor),
        });

        var serializer          = new ConfigurationEditorJsonSerializer();
        var dataTypeServiceMock = new Mock <IDataTypeService>();
        var dataType            = new DataType(
            new VoidEditor(Mock.Of <IDataValueEditorFactory>()), serializer)
        {
            Id = 1
        };

        dataTypeServiceMock.Setup(x => x.GetAll()).Returns(dataType.Yield);

        var contentTypeFactory =
            new PublishedContentTypeFactory(Mock.Of <IPublishedModelFactory>(), converters, dataTypeServiceMock.Object);

        IEnumerable <IPublishedPropertyType> CreatePropertyTypes(IPublishedContentType contentType)
        {
            yield return(contentTypeFactory.CreatePropertyType(contentType, "prop1", 1));
        }

        var elementType1 = contentTypeFactory.CreateContentType(Guid.NewGuid(), 1000, "element1", CreatePropertyTypes);

        var element1 = new PublishedElement(elementType1, Guid.NewGuid(), new Dictionary <string, object> {
            { "prop1", "1234" }
        }, false);

        var cntType1 = contentTypeFactory.CreateContentType(Guid.NewGuid(), 1001, "cnt1", t => Enumerable.Empty <PublishedPropertyType>());
        var cnt1     = new InternalPublishedContent(cntType1)
        {
            Id = 1234
        };

        cacheContent[cnt1.Id] = cnt1;

        Assert.AreSame(cnt1, element1.Value(Mock.Of <IPublishedValueFallback>(), "prop1"));
    }
        public void SimpleConverter3Test()
        {
            var register = new ServiceCollection();

            var composition = new UmbracoBuilder(register, Mock.Of <IConfiguration>(), TestHelper.GetMockedTypeLoader());

            composition.WithCollectionBuilder <PropertyValueConverterCollectionBuilder>()
            .Append <SimpleConverter3A>()
            .Append <SimpleConverter3B>();

            IPublishedModelFactory factory = new PublishedModelFactory(
                new[]
            {
                typeof(PublishedSnapshotTestObjects.TestElementModel1),
                typeof(PublishedSnapshotTestObjects.TestElementModel2),
                typeof(PublishedSnapshotTestObjects.TestContentModel1),
                typeof(PublishedSnapshotTestObjects.TestContentModel2)
            }, Mock.Of <IPublishedValueFallback>());

            register.AddTransient(f => factory);

            var cacheMock    = new Mock <IPublishedContentCache>();
            var cacheContent = new Dictionary <int, IPublishedContent>();

            cacheMock.Setup(x => x.GetById(It.IsAny <int>())).Returns <int>(id =>
                                                                            cacheContent.TryGetValue(id, out IPublishedContent content) ? content : null);
            var publishedSnapshotMock = new Mock <IPublishedSnapshot>();

            publishedSnapshotMock.Setup(x => x.Content).Returns(cacheMock.Object);
            var publishedSnapshotAccessorMock = new Mock <IPublishedSnapshotAccessor>();
            var localPublishedSnapshot        = publishedSnapshotMock.Object;

            publishedSnapshotAccessorMock.Setup(x => x.TryGetPublishedSnapshot(out localPublishedSnapshot)).Returns(true);
            register.AddTransient(f => publishedSnapshotAccessorMock.Object);

            IServiceProvider registerFactory            = composition.CreateServiceProvider();
            PropertyValueConverterCollection converters =
                registerFactory.GetRequiredService <PropertyValueConverterCollection>();

            var serializer          = new ConfigurationEditorJsonSerializer();
            var dataTypeServiceMock = new Mock <IDataTypeService>();
            var dataType1           = new DataType(
                new VoidEditor(
                    Mock.Of <IDataValueEditorFactory>()),
                serializer)
            {
                Id = 1
            };
            var dataType2 = new DataType(
                new VoidEditor(
                    "2",
                    Mock.Of <IDataValueEditorFactory>()),
                serializer)
            {
                Id = 2
            };

            dataTypeServiceMock.Setup(x => x.GetAll()).Returns(new[] { dataType1, dataType2 });

            var contentTypeFactory = new PublishedContentTypeFactory(factory, converters, dataTypeServiceMock.Object);

            IEnumerable <IPublishedPropertyType> CreatePropertyTypes(IPublishedContentType contentType, int i)
            {
                yield return(contentTypeFactory.CreatePropertyType(contentType, "prop" + i, i));
            }

            IPublishedContentType elementType1 =
                contentTypeFactory.CreateContentType(Guid.NewGuid(), 1000, "element1", t => CreatePropertyTypes(t, 1));
            IPublishedContentType elementType2 =
                contentTypeFactory.CreateContentType(Guid.NewGuid(), 1001, "element2", t => CreatePropertyTypes(t, 2));
            IPublishedContentType contentType1 =
                contentTypeFactory.CreateContentType(Guid.NewGuid(), 1002, "content1", t => CreatePropertyTypes(t, 1));
            IPublishedContentType contentType2 =
                contentTypeFactory.CreateContentType(Guid.NewGuid(), 1003, "content2", t => CreatePropertyTypes(t, 2));

            var element1 = new PublishedElement(
                elementType1,
                Guid.NewGuid(),
                new Dictionary <string, object> {
                { "prop1", "val1" }
            },
                false);
            var element2 = new PublishedElement(
                elementType2,
                Guid.NewGuid(),
                new Dictionary <string, object> {
                { "prop2", "1003" }
            },
                false);
            var cnt1 = new InternalPublishedContent(contentType1)
            {
                Id         = 1003,
                Properties = new[]
                {
                    new InternalPublishedProperty {
                        Alias = "prop1", SolidHasValue = true, SolidValue = "val1"
                    }
                }
            };
            var cnt2 = new InternalPublishedContent(contentType1)
            {
                Id         = 1004,
                Properties = new[]
                {
                    new InternalPublishedProperty {
                        Alias = "prop2", SolidHasValue = true, SolidValue = "1003"
                    }
                }
            };

            IPublishedModelFactory publishedModelFactory = registerFactory.GetRequiredService <IPublishedModelFactory>();

            cacheContent[cnt1.Id] = cnt1.CreateModel(publishedModelFactory);
            cacheContent[cnt2.Id] = cnt2.CreateModel(publishedModelFactory);

            // can get the actual property Clr type
            // ie ModelType gets properly mapped by IPublishedContentModelFactory
            // must test ModelClrType with special equals 'cos they are not ref-equals
            Assert.IsTrue(ModelType.Equals(
                              typeof(IEnumerable <>).MakeGenericType(ModelType.For("content1")),
                              contentType2.GetPropertyType("prop2").ModelClrType));
            Assert.AreEqual(
                typeof(IEnumerable <PublishedSnapshotTestObjects.TestContentModel1>),
                contentType2.GetPropertyType("prop2").ClrType);

            // can create a model for an element
            IPublishedElement model1 = factory.CreateModel(element1);

            Assert.IsInstanceOf <PublishedSnapshotTestObjects.TestElementModel1>(model1);
            Assert.AreEqual("val1", ((PublishedSnapshotTestObjects.TestElementModel1)model1).Prop1);

            // can create a model for a published content
            IPublishedElement model2 = factory.CreateModel(element2);

            Assert.IsInstanceOf <PublishedSnapshotTestObjects.TestElementModel2>(model2);
            var mmodel2 = (PublishedSnapshotTestObjects.TestElementModel2)model2;

            // and get direct property
            Assert.IsInstanceOf <PublishedSnapshotTestObjects.TestContentModel1[]>(
                model2.Value(Mock.Of <IPublishedValueFallback>(), "prop2"));
            Assert.AreEqual(
                1,
                ((PublishedSnapshotTestObjects.TestContentModel1[])model2.Value(Mock.Of <IPublishedValueFallback>(), "prop2")).Length);

            // and get model property
            Assert.IsInstanceOf <IEnumerable <PublishedSnapshotTestObjects.TestContentModel1> >(mmodel2.Prop2);
            Assert.IsInstanceOf <PublishedSnapshotTestObjects.TestContentModel1[]>(mmodel2.Prop2);
            PublishedSnapshotTestObjects.TestContentModel1 mmodel1 = mmodel2.Prop2.First();

            // and we get what we want
            Assert.AreSame(cacheContent[mmodel1.Id], mmodel1);
        }