public Task If_InternalName_null()
        {
            var prov = new HarshField()
            {
                Id = Guid.NewGuid(),
            };

            return Assert.ThrowsAsync<ParameterValidationException>(
                () => prov.ProvisionAsync(Context)
            );
        }
        public Task If_Id_empty()
        {
            var prov = new HarshField()
            {
                InternalName = Guid.NewGuid().ToString("n")
            };

            return Assert.ThrowsAsync<ParameterValidationException>(
                () => prov.ProvisionAsync(Context)
            );
        }
        public async Task Field_is_not_created()
        {
            var prov = new HarshField()
            {
                Id = HarshBuiltInFieldId.Title,
            };

            await prov.ProvisionAsync(Context);
            var fo = LastObjectOutput<Field>();

            Assert.False(fo.ObjectAdded);
        }
        public async Task Lookup_has_correct_list_id()
        {
            var targetList = await EnsureTargetList();

            var lookupField = new HarshModifyFieldLookup()
            {
                LookupTarget = Resolve
                    .List().ByUrl(TargetListUrl)
                    .Field().ById(HarshBuiltInFieldId.Title)
                    .As<Tuple<List, Field>>()
            };

            var fieldId = Guid.NewGuid();
            var field = new HarshField()
            {
                Id = fieldId,
                InternalName = fieldId.ToString("n"),
                Type = FieldType.Lookup,

                Children =
                {
                    lookupField
                }
            };

            await field.ProvisionAsync(Context);

            var fo = LastObjectOutput<Field>();
            Assert.True(fo.ObjectAdded);

            ClientContext.Load(
                ClientContext.CastTo<FieldLookup>(fo.Object),
                f => f.FieldTypeKind,
                f => f.LookupField,
                f => f.LookupList,
                f => f.LookupWebId
            );

            ClientContext.Load(Web, w => w.Id);
            ClientContext.Load(targetList, l => l.Id);

            await ClientContext.ExecuteQueryAsync();

            var provisioned = fo.Object as FieldLookup;

            Assert.NotNull(provisioned);
            Assert.Equal(FieldType.Lookup, provisioned.FieldTypeKind);
            Assert.Equal(targetList.Id, Guid.Parse(provisioned.LookupList));
            Assert.Equal("Title", provisioned.LookupField);
            Assert.Equal(Web.Id, provisioned.LookupWebId);
        }
        public async Task Id_is_set()
        {
            var fieldId = Guid.NewGuid();
            var fieldName = fieldId.ToString("n");

            var provisioner = new HarshField()
            {
                Id = fieldId,
                InternalName = fieldName,
                Type = FieldType.Text,
            };

            await provisioner.ProvisionAsync(Context);

            var fieldOutput = LastObjectOutput<Field>();
            var field = fieldOutput.Object;

            ClientContext.Load(field, f => f.Id);
            await Context.ClientContext.ExecuteQueryAsync();

            Assert.Equal(fieldId, field.Id);
        }
        public async Task Field_is_created()
        {
            var fieldId = Guid.NewGuid();
            var fieldName = fieldId.ToString("n");

            var provisioner = new HarshField()
            {
                Id = fieldId,
                InternalName = fieldName,
                Type = FieldType.Text,
            };

            await provisioner.ProvisionAsync(Context);

            var fieldOutput = LastObjectOutput<Field>();
            Assert.True(fieldOutput.ObjectAdded);

            var field = fieldOutput.Object;
            Assert.NotNull(field);
        }
        public async Task Field_is_removed_by_id()
        {
            var field = await CreateField(f => f.Id);

            var prov = new HarshField()
            {
                MayDeleteUserData = true,
                Id = field.Id,
            };

            await prov.UnprovisionAsync(Context);

            var output = LastIdentifiedOutput();
            Assert.Equal(prov.Id.ToStringInvariant(), output.Identifier);
            Assert.False(output.ObjectAdded);
            Assert.True(output.ObjectRemoved);

            var fields = ClientContext.LoadQuery(Web.Fields.Include(f => f.Id));
            await ClientContext.ExecuteQueryAsync();

            Assert.DoesNotContain(field.Id, fields.Select(f => f.Id));
        }
        public async Task Nonexistent_field_is_not_removed()
        {
            var prov = new HarshField()
            {
                MayDeleteUserData = true,
                Id = Guid.NewGuid()
            };

            await prov.UnprovisionAsync(Context);

            var output = LastIdentifiedOutput();
            Assert.Equal(prov.Id.ToStringInvariant(), output.Identifier);
            Assert.False(output.ObjectAdded);
            Assert.False(output.ObjectRemoved);
        }
        public async Task Child_fieldref_get_added()
        {
            var fieldId = Guid.NewGuid();

            var field = new HarshField()
            {
                Id = fieldId,
                InternalName = fieldId.ToString("n"),
                Type = FieldType.Text,
            };

            var ct = new HarshContentType()
            {
                Id = _id,
                Name = _guid,
                Description = _guid,
                Group = Group,
                Children =
                {
                    new HarshFieldRef()
                    {
                        Fields = Resolve.Field().ById(fieldId),
                    },
                }
            };

            try
            {
                await field.ProvisionAsync(Context);
                await ct.ProvisionAsync(Context);

                var cto = LastObjectOutput<ContentType>();

                Assert.True(cto.ObjectAdded);
                Assert.False(cto.Object.IsNull());

                var links = ClientContext.LoadQuery(
                    cto.Object.FieldLinks
                    .Where(fl => fl.Id == fieldId)
                    .Include(
                        fl => fl.Name,
                        fl => fl.Id
                    )
                );

                await ClientContext.ExecuteQueryAsync();

                var link = Assert.Single(links);

                Assert.NotNull(link);
                Assert.Equal(fieldId, link.Id);
                Assert.Equal(field.InternalName, link.Name);
            }
            finally
            {
                try
                {
                    Web.ContentTypes.GetById(_id.ToString()).DeleteObject();
                }
                finally
                {
                    Web.Fields.GetById(fieldId).DeleteObject();
                }
            }
        }