public void Parse_ValidSelection_CanParse() { // Arrange const string type = "articles"; const string attrName = "someField"; var attribute = new AttrAttribute(attrName); var idAttribute = new AttrAttribute("id"); var query = new KeyValuePair <string, StringValues>("fields", new StringValues(attrName)); var resourceContext = new ResourceContext { ResourceName = type, Attributes = new List <AttrAttribute> { attribute, idAttribute }, Relationships = new List <RelationshipAttribute>() }; var service = GetService(resourceContext); // Act service.Parse(query); var result = service.Get(); // Assert Assert.NotEmpty(result); Assert.Equal(idAttribute, result.First()); Assert.Equal(attribute, result[1]); }
private bool ShouldIncludeAttribute(AttrAttribute attr, object attributeValue) { return(OmitNullValuedAttribute(attr, attributeValue) == false && ((_jsonApiContext.QuerySet == null || _jsonApiContext.QuerySet.Fields.Count == 0) || _jsonApiContext.QuerySet.Fields.Contains(attr.InternalAttributeName))); }
public void Parse_ValidSelection_CanParse() { // Arrange const string type = "articles"; const string attrName = "name"; var attribute = new AttrAttribute(attrName) { PropertyInfo = typeof(Article).GetProperty(nameof(Article.Name)) }; var idAttribute = new AttrAttribute("id") { PropertyInfo = typeof(Article).GetProperty(nameof(Article.Id)) }; var query = new KeyValuePair <string, StringValues>("fields", attrName); var resourceContext = new ResourceContext { ResourceName = type, Attributes = new List <AttrAttribute> { attribute, idAttribute }, Relationships = new List <RelationshipAttribute>() }; var service = GetService(resourceContext); // Act service.Parse(query.Key, query.Value); var result = service.Get(); // Assert Assert.NotEmpty(result); Assert.Contains(idAttribute, result); Assert.Contains(attribute, result); }
public void Parse_DeeplyNestedSelection_ThrowsJsonApiException() { // Arrange const string type = "articles"; const string relationship = "author.employer"; const string attrName = "someField"; var attribute = new AttrAttribute(attrName); var idAttribute = new AttrAttribute("id"); var queryParameterName = $"fields[{relationship}]"; var query = new KeyValuePair <string, StringValues>(queryParameterName, attrName); var resourceContext = new ResourceContext { ResourceName = type, Attributes = new List <AttrAttribute> { attribute, idAttribute }, Relationships = new List <RelationshipAttribute>() }; var service = GetService(resourceContext); // Act, assert var exception = Assert.Throws <InvalidQueryStringParameterException>(() => service.Parse(query.Key, query.Value)); Assert.Equal(queryParameterName, exception.QueryParameterName); Assert.Equal(HttpStatusCode.BadRequest, exception.Error.StatusCode); Assert.Equal("Deeply nested sparse field selection is currently not supported.", exception.Error.Title); Assert.Equal($"Parameter fields[{relationship}] is currently not supported.", exception.Error.Detail); Assert.Equal(queryParameterName, exception.Error.Source.Parameter); }
public void Parse_InvalidField_ThrowsJsonApiException() { // Arrange const string type = "articles"; const string attrName = "dne"; var idAttribute = new AttrAttribute("id") { PropertyInfo = typeof(Article).GetProperty(nameof(Article.Id)) }; var query = new KeyValuePair <string, StringValues>("fields", attrName); var resourceContext = new ResourceContext { ResourceName = type, Attributes = new List <AttrAttribute> { idAttribute }, Relationships = new List <RelationshipAttribute>() }; var service = GetService(resourceContext); // Act, assert var exception = Assert.Throws <InvalidQueryStringParameterException>(() => service.Parse(query.Key, query.Value)); Assert.Equal("fields", exception.QueryParameterName); Assert.Equal(HttpStatusCode.BadRequest, exception.Error.StatusCode); Assert.Equal("The specified field does not exist on the requested resource.", exception.Error.Title); Assert.Equal($"The field '{attrName}' does not exist on resource '{type}'.", exception.Error.Detail); Assert.Equal("fields", exception.Error.Source.Parameter); }
/// <inheritdoc /> public QueryLayer ComposeForHasMany <TId>(HasManyAttribute hasManyRelationship, TId leftId, ICollection <IIdentifiable> rightResourceIds) { ArgumentGuard.NotNull(hasManyRelationship, nameof(hasManyRelationship)); ArgumentGuard.NotNull(rightResourceIds, nameof(rightResourceIds)); ResourceContext leftResourceContext = _resourceContextProvider.GetResourceContext(hasManyRelationship.LeftType); AttrAttribute leftIdAttribute = GetIdAttribute(leftResourceContext); ResourceContext rightResourceContext = _resourceContextProvider.GetResourceContext(hasManyRelationship.RightType); AttrAttribute rightIdAttribute = GetIdAttribute(rightResourceContext); object[] rightTypedIds = rightResourceIds.Select(resource => resource.GetTypedId()).ToArray(); FilterExpression leftFilter = CreateFilterByIds(leftId.AsArray(), leftIdAttribute, null); FilterExpression rightFilter = CreateFilterByIds(rightTypedIds, rightIdAttribute, null); return(new QueryLayer(leftResourceContext) { Include = new IncludeExpression(new IncludeElementExpression(hasManyRelationship).AsArray()), Filter = leftFilter, Projection = new Dictionary <ResourceFieldAttribute, QueryLayer> { [hasManyRelationship] = new QueryLayer(rightResourceContext) { Filter = rightFilter, Projection = new Dictionary <ResourceFieldAttribute, QueryLayer> { [rightIdAttribute] = null } }, [leftIdAttribute] = null } }); }
/// <inheritdoc /> public QueryLayer WrapLayerForSecondaryEndpoint <TId>(QueryLayer secondaryLayer, ResourceContext primaryResourceContext, TId primaryId, RelationshipAttribute secondaryRelationship) { ArgumentGuard.NotNull(secondaryLayer, nameof(secondaryLayer)); ArgumentGuard.NotNull(primaryResourceContext, nameof(primaryResourceContext)); ArgumentGuard.NotNull(secondaryRelationship, nameof(secondaryRelationship)); IncludeExpression innerInclude = secondaryLayer.Include; secondaryLayer.Include = null; IReadOnlyCollection <AttrAttribute> primaryAttributeSet = _sparseFieldSetCache.GetIdAttributeSetForRelationshipQuery(primaryResourceContext); Dictionary <ResourceFieldAttribute, QueryLayer> primaryProjection = primaryAttributeSet.ToDictionary(key => (ResourceFieldAttribute)key, _ => (QueryLayer)null); primaryProjection[secondaryRelationship] = secondaryLayer; FilterExpression primaryFilter = GetFilter(Array.Empty <QueryExpression>(), primaryResourceContext); AttrAttribute primaryIdAttribute = GetIdAttribute(primaryResourceContext); return(new QueryLayer(primaryResourceContext) { Include = RewriteIncludeForSecondaryEndpoint(innerInclude, secondaryRelationship), Filter = CreateFilterByIds(primaryId.AsArray(), primaryIdAttribute, primaryFilter), Projection = primaryProjection }); }
/// <inheritdoc /> public QueryLayer ComposeForGetById <TId>(TId id, ResourceContext resourceContext, TopFieldSelection fieldSelection) { ArgumentGuard.NotNull(resourceContext, nameof(resourceContext)); AttrAttribute idAttribute = GetIdAttribute(resourceContext); QueryLayer queryLayer = ComposeFromConstraints(resourceContext); queryLayer.Sort = null; queryLayer.Pagination = null; queryLayer.Filter = CreateFilterByIds(id.AsArray(), idAttribute, queryLayer.Filter); if (fieldSelection == TopFieldSelection.OnlyIdAttribute) { queryLayer.Projection = new Dictionary <ResourceFieldAttribute, QueryLayer> { [idAttribute] = null }; } else if (fieldSelection == TopFieldSelection.WithAllAttributes && queryLayer.Projection != null) { // Discard any top-level ?fields[]= or attribute exclusions from resource definition, because we need the full database row. while (queryLayer.Projection.Any(pair => pair.Key is AttrAttribute)) { queryLayer.Projection.Remove(queryLayer.Projection.First(pair => pair.Key is AttrAttribute)); } } return(queryLayer); }
public void Parse_InvalidRelationship_ThrowsJsonApiException() { // Arrange const string type = "articles"; var attrName = "someField"; var attribute = new AttrAttribute(attrName); var idAttribute = new AttrAttribute("id"); var queryParameterName = "fields[missing]"; var query = new KeyValuePair <string, StringValues>(queryParameterName, attrName); var resourceContext = new ResourceContext { ResourceName = type, Attributes = new List <AttrAttribute> { attribute, idAttribute }, Relationships = new List <RelationshipAttribute>() }; var service = GetService(resourceContext); // Act, assert var exception = Assert.Throws <InvalidQueryStringParameterException>(() => service.Parse(query.Key, query.Value)); Assert.Equal(queryParameterName, exception.QueryParameterName); Assert.Equal(HttpStatusCode.BadRequest, exception.Error.StatusCode); Assert.Equal("Sparse field navigation path refers to an invalid relationship.", exception.Error.Title); Assert.Equal("'missing' in 'fields[missing]' is not a valid relationship of articles.", exception.Error.Detail); Assert.Equal(queryParameterName, exception.Error.Source.Parameter); }
public void Parse_DeeplyNestedSelection_Throws400ErrorWithDeeplyNestedMessage() { // Arrange const string type = "articles"; const string relationship = "author.employer"; const string attrName = "someField"; var attribute = new AttrAttribute(attrName); var idAttribute = new AttrAttribute("id"); var query = new KeyValuePair <string, StringValues>($"fields[{relationship}]", new StringValues(attrName)); var resourceContext = new ResourceContext { ResourceName = type, Attributes = new List <AttrAttribute> { attribute, idAttribute }, Relationships = new List <RelationshipAttribute>() }; var service = GetService(resourceContext); // Act, assert var ex = Assert.Throws <JsonApiException>(() => service.Parse(query)); Assert.Contains("deeply nested", ex.Message); }
public void Parse_TypeNameAsNavigation_Throws400ErrorWithRelationshipsOnlyMessage() { // Arrange const string type = "articles"; const string attrName = "someField"; const string internalAttrName = "SomeField"; var attribute = new AttrAttribute(attrName) { InternalAttributeName = internalAttrName }; var idAttribute = new AttrAttribute("id") { InternalAttributeName = "Id" }; var query = new KeyValuePair <string, StringValues>($"fields[{type}]", new StringValues(attrName)); var resourceContext = new ResourceContext { ResourceName = type, Attributes = new List <AttrAttribute> { attribute, idAttribute }, Relationships = new List <RelationshipAttribute>() }; var service = GetService(resourceContext); // Act, assert var ex = Assert.Throws <JsonApiException>(() => service.Parse(query)); Assert.Contains("relationships only", ex.Message); }
public void AttrAttribute_Equals_Returns_True_When_Same_Name() { var a = new AttrAttribute("test"); var b = new AttrAttribute("test"); Assert.Equal(a, b); }
public override async Task <IActionResult> PatchAsync(int id, [FromBody] PatientVitals patientVital) { //var attrToUpdate = _jsonApiContext.AttributesToUpdate; //var patientVitalOld = _dbContextResolver.GetDbSet<PatientVitals>().Where(m => m.Id == id).FirstOrDefault(); //CommonMethods commonMethods = new CommonMethods(); //List<AuditLogs> auditLogs = commonMethods.GetAuditLogValues(patientVitalOld, patientVital, "PatientVitals", attrToUpdate) // //.Where(i => attrToUpdate.Keys.Any(a1 => a1.InternalAttributeName == i.PropertyName)) // .Select(q => new AuditLogs() { NewValue = q.NewValue, OldValue = q.OldValue, PrimaryKeyID = q.PrimaryKeyID, TableName = q.TableName, PropertyName = q.PropertyName }).ToList(); //await _dbContextResolver.GetDbSet<AuditLogs>().AddRangeAsync(auditLogs); AttrAttribute BMI = new AttrAttribute(AttrToUpdate.BMI.ToString(), AttrToUpdate.BMI.ToString()); _jsonApiContext.AttributesToUpdate.Remove(BMI); patientVital = calculateBmi(patientVital); _jsonApiContext.AttributesToUpdate.Add(BMI, patientVital.BMI); //return await base.PatchAsync(id, patientVital); //var patientVitalInfo = await base.PatchAsync(id, patientVital); //int eventID = _dbContextResolver.GetDbSet<Event>().LastOrDefault().Id + 1; //List<AuditLogs> auditLogs = commonMethods.GetAuditLogValues(patientVitalOld, patientVital, "PatientVitals", attrToUpdate) // //.Where(i => attrToUpdate.Keys.Any(a1 => a1.InternalAttributeName == i.PropertyName)) // .Select(q => new AuditLogs() { NewValue = q.NewValue, OldValue = q.OldValue, PrimaryKeyID = q.PrimaryKeyID, TableName = q.TableName, PropertyName = q.PropertyName, EventID = eventID }).ToList(); //await _dbContextResolver.GetDbSet<AuditLogs>().AddRangeAsync(auditLogs); return(await base.PatchAsync(id, patientVital)); }
public async Task UpdateAsync_Updates_Attributes_In_AttributesToUpdate() { // arrange var todoItemUpdates = new TodoItem { Id = _todoItem.Id, Description = Guid.NewGuid().ToString() }; var descAttr = new AttrAttribute("description", "Description"); descAttr.PropertyInfo = typeof(TodoItem).GetProperty(nameof(TodoItem.Description)); _attrsToUpdate = new Dictionary <AttrAttribute, object> { { descAttr, null //todoItemUpdates.Description } }; var repository = GetRepository(); // act var updatedItem = await repository.UpdateAsync(todoItemUpdates); // assert Assert.NotNull(updatedItem); Assert.Equal(_todoItem.Ordinal, updatedItem.Ordinal); Assert.Equal(todoItemUpdates.Description, updatedItem.Description); }
private FilterExpression CreateFilterByIds <TId>(ICollection <TId> ids, AttrAttribute idAttribute, FilterExpression existingFilter) { var idChain = new ResourceFieldChainExpression(idAttribute); FilterExpression filter = null; if (ids.Count == 1) { var constant = new LiteralConstantExpression(ids.Single().ToString()); filter = new ComparisonExpression(ComparisonOperator.Equals, idChain, constant); } else if (ids.Count > 1) { var constants = ids.Select(id => new LiteralConstantExpression(id.ToString())).ToList(); filter = new EqualsAnyOfExpression(idChain, constants); } // @formatter:keep_existing_linebreaks true return(filter == null ? existingFilter : existingFilter == null ? filter : new LogicalExpression(LogicalOperator.And, ArrayFactory.Create(filter, existingFilter))); // @formatter:keep_existing_linebreaks restore }
protected virtual List <AttrAttribute> GetAttributes(Type entityType) { var attributes = new List <AttrAttribute>(); var properties = entityType.GetProperties(); foreach (var prop in properties) { // todo: investigate why this is added in the exposed attributes list // because it is not really defined attribute considered from the json:api // spec point of view. if (prop.Name == nameof(Identifiable.Id)) { var idAttr = new AttrAttribute { PublicAttributeName = FormatPropertyName(prop), PropertyInfo = prop }; attributes.Add(idAttr); continue; } var attribute = (AttrAttribute)prop.GetCustomAttribute(typeof(AttrAttribute)); if (attribute == null) { continue; } attribute.PublicAttributeName ??= FormatPropertyName(prop); attribute.PropertyInfo = prop; attributes.Add(attribute); } return(attributes); }
protected virtual List <AttrAttribute> GetAttributes(Type entityType) { var attributes = new List <AttrAttribute>(); var properties = entityType.GetProperties(); foreach (var prop in properties) { if (prop.Name == nameof(Identifiable.Id)) { var idAttr = new AttrAttribute() { PublicAttributeName = JsonApiOptions.ResourceNameFormatter.FormatPropertyName(prop), PropertyInfo = prop, InternalAttributeName = prop.Name }; attributes.Add(idAttr); continue; } var attribute = (AttrAttribute)prop.GetCustomAttribute(typeof(AttrAttribute)); if (attribute == null) { continue; } attribute.PublicAttributeName = attribute.PublicAttributeName ?? JsonApiOptions.ResourceNameFormatter.FormatPropertyName(prop); attribute.InternalAttributeName = prop.Name; attribute.PropertyInfo = prop; attributes.Add(attribute); } return(attributes); }
public override async Task <IActionResult> PatchAsync(int id, [FromBody] Patients patientInfo) { // var attrToUpdate= _jsonApiContext.AttributesToUpdate; //var patientInfoOld = _dbContextResolver.GetDbSet<Patients>().Where(m => m.Id == id).FirstOrDefault(); CommonMethods commonMethods = new CommonMethods(); AttrAttribute photoPath = new AttrAttribute(AttrToUpdate.PhotoPath.ToString(), AttrToUpdate.PhotoPath.ToString()); AttrAttribute photoThumbnailPath = new AttrAttribute(AttrToUpdate.PhotoThumbnailPath.ToString(), AttrToUpdate.PhotoThumbnailPath.ToString()); if (!string.IsNullOrEmpty(patientInfo.PhotoBase64)) { _jsonApiContext.AttributesToUpdate.Remove(photoPath); _jsonApiContext.AttributesToUpdate.Remove(photoThumbnailPath); patientInfo = ConvertBase64ToImage(patientInfo, commonMethods); if (!string.IsNullOrEmpty(patientInfo.PhotoPath) && !string.IsNullOrEmpty(patientInfo.PhotoThumbnailPath)) { _jsonApiContext.AttributesToUpdate.Add(photoPath, patientInfo.PhotoPath); _jsonApiContext.AttributesToUpdate.Add(photoThumbnailPath, patientInfo.PhotoThumbnailPath); } } //var patientDetails = await base.PatchAsync(id, patientInfo); //int eventID = _dbContextResolver.GetDbSet<Event>().AsQueryable().OrderByDescending(p => p.Id).FirstOrDefault().Id + 1; //List<AuditLogs> auditLogs = commonMethods.GetAuditLogValues(patientInfoOld, patientInfo, "Patients", attrToUpdate) // //.Where(i=> attrToUpdate.Keys.Any(a1 => a1.InternalAttributeName == i.PropertyName)) // .Select(q => new AuditLogs() { NewValue = q.NewValue, OldValue = q.OldValue, PrimaryKeyID = q.PrimaryKeyID, TableName = q.TableName, PropertyName = q.PropertyName, EventID = eventID }).ToList(); //await _dbContextResolver.GetDbSet<AuditLogs>().AddRangeAsync(auditLogs); return(await base.PatchAsync(id, patientInfo)); }
public void AttrAttribute_Equals_Returns_False_When_Different_Name() { var a = new AttrAttribute("test"); var b = new AttrAttribute("test2"); Assert.NotEqual(a, b); }
public async Task UpdateAsync_AttributesUpdated_ShouldHaveSpecificallyThoseAttributesUpdated() { // Arrange var itemId = 213; var seed = Guid.NewGuid(); var databaseResource = new TodoItem { Id = itemId, Description = "Before" }; var todoItemUpdates = new TodoItem { Id = itemId, Description = "After" }; await using (var arrangeDbContext = GetDbContext(seed)) { var(repository, targetedFields, _) = Setup(arrangeDbContext); arrangeDbContext.Add(databaseResource); await arrangeDbContext.SaveChangesAsync(); var descAttr = new AttrAttribute { PublicName = "description", Property = typeof(TodoItem).GetProperty(nameof(TodoItem.Description)) }; targetedFields.Setup(m => m.Attributes).Returns(new List <AttrAttribute> { descAttr }); targetedFields.Setup(m => m.Relationships).Returns(new List <RelationshipAttribute>()); // Act await repository.UpdateAsync(todoItemUpdates, databaseResource); } // Assert - in different context await using (var assertDbContext = GetDbContext(seed)) { var(repository, _, resourceGraph) = Setup(assertDbContext); var resourceContext = resourceGraph.GetResourceContext <TodoItem>(); var idAttribute = resourceContext.Attributes.Single(a => a.Property.Name == nameof(Identifiable.Id)); var resources = await repository.GetAsync(new QueryLayer(resourceContext) { Filter = new ComparisonExpression(ComparisonOperator.Equals, new ResourceFieldChainExpression(idAttribute), new LiteralConstantExpression(itemId.ToString())) }); var fetchedTodo = resources.First(); Assert.NotNull(fetchedTodo); Assert.Equal(databaseResource.Ordinal, fetchedTodo.Ordinal); Assert.Equal(todoItemUpdates.Description, fetchedTodo.Description); } }
public CarExpressionRewriter(IResourceContextProvider resourceContextProvider) { ResourceContext carResourceContext = resourceContextProvider.GetResourceContext <Car>(); _regionIdAttribute = carResourceContext.Attributes.Single(attribute => attribute.Property.Name == nameof(Car.RegionId)); _licensePlateAttribute = carResourceContext.Attributes.Single(attribute => attribute.Property.Name == nameof(Car.LicensePlate)); }
private void ValidateSingleAttribute(AttrAttribute attribute, ResourceContext resourceContext, string path) { if (!attribute.Capabilities.HasFlag(AttrCapabilities.AllowView)) { throw new InvalidQueryStringParameterException(_lastParameterName, "Retrieving the requested attribute is not allowed.", $"Retrieving the attribute '{attribute.PublicName}' is not allowed."); } }
private bool ShouldIncludeAttribute(AttrAttribute attr, object attributeValue, RelationshipAttribute relationship = null) { return(OmitNullValuedAttribute(attr, attributeValue) == false && attr.InternalAttributeName != nameof(Identifiable.Id) && ((_jsonApiContext.QuerySet == null || _jsonApiContext.QuerySet.Fields.Count == 0) || _jsonApiContext.QuerySet.Fields.Contains(relationship != null ? $"{relationship.InternalRelationshipName}.{attr.InternalAttributeName}" : attr.InternalAttributeName))); }
private SparseFieldSetExpression GetSparseFieldSet(string parameterValue, ResourceContext resourceContext) { SparseFieldSetExpression sparseFieldSet = _sparseFieldSetParser.Parse(parameterValue, resourceContext); if (sparseFieldSet == null) { // We add ID on an incoming empty fieldset, so that callers can distinguish between no fieldset and an empty one. AttrAttribute idAttribute = resourceContext.Attributes.Single(attribute => attribute.Property.Name == nameof(Identifiable.Id)); return(new SparseFieldSetExpression(ArrayFactory.Create(idAttribute))); } return(sparseFieldSet); }
public void AttrAttribute_Equals_Returns_False_When_Different_Name() { var attribute1 = new AttrAttribute { PublicName = "test" }; var attribute2 = new AttrAttribute { PublicName = "test2" }; Assert.NotEqual(attribute1, attribute2); }
public void AttrAttribute_Equals_Returns_True_When_Same_Name() { var attribute1 = new AttrAttribute { PublicName = "test" }; var attribute2 = new AttrAttribute { PublicName = "test" }; Assert.Equal(attribute1, attribute2); }
public override FilterExpression OnApplyFilter(FilterExpression existingFilter) { ResourceContext resourceContext = _resourceGraph.GetResourceContext <TResource>(); AttrAttribute isSoftDeletedAttribute = resourceContext.Attributes.Single(attribute => attribute.Property.Name == nameof(ISoftDeletable.IsSoftDeleted)); var isNotSoftDeleted = new ComparisonExpression(ComparisonOperator.Equals, new ResourceFieldChainExpression(isSoftDeletedAttribute), new LiteralConstantExpression("false")); return(existingFilter == null ? (FilterExpression)isNotSoftDeleted : new LogicalExpression(LogicalOperator.And, ArrayFactory.Create(isNotSoftDeleted, existingFilter))); }
public override FilterExpression OnApplyFilter(FilterExpression existingFilter) { // Use case: automatically exclude deleted resources for all requests. ResourceContext resourceContext = ResourceGraph.GetResourceContext <CallableResource>(); AttrAttribute isDeletedAttribute = resourceContext.Attributes.Single(attribute => attribute.Property.Name == nameof(CallableResource.IsDeleted)); var isNotDeleted = new ComparisonExpression(ComparisonOperator.Equals, new ResourceFieldChainExpression(isDeletedAttribute), new LiteralConstantExpression(bool.FalseString)); return(existingFilter == null ? (FilterExpression)isNotDeleted : new LogicalExpression(LogicalOperator.And, ArrayFactory.Create(isNotDeleted, existingFilter))); }
private static FilterExpression CreateFilterByIds <TId>(IReadOnlyCollection <TId> ids, ResourceContext resourceContext) { AttrAttribute idAttribute = resourceContext.Attributes.Single(attr => attr.Property.Name == nameof(Identifiable.Id)); var idChain = new ResourceFieldChainExpression(idAttribute); if (ids.Count == 1) { var constant = new LiteralConstantExpression(ids.Single().ToString()); return(new ComparisonExpression(ComparisonOperator.Equals, idChain, constant)); } List <LiteralConstantExpression> constants = ids.Select(id => new LiteralConstantExpression(id.ToString())).ToList(); return(new EqualsAnyOfExpression(idChain, constants)); }
public async Task UpdateAsync_AttributesUpdated_ShouldHaveSpecificallyThoseAttributesUpdated() { // Arrange var itemId = 213; var seed = Guid.NewGuid(); var databaseEntity = new TodoItem { Id = itemId, Description = "Before" }; var todoItemUpdates = new TodoItem { Id = itemId, Description = "After" }; await using (var arrangeContext = GetContext(seed)) { var(repository, targetedFields) = Setup(arrangeContext); arrangeContext.Add(databaseEntity); arrangeContext.SaveChanges(); var descAttr = new AttrAttribute("description") { PropertyInfo = typeof(TodoItem).GetProperty(nameof(TodoItem.Description)) }; targetedFields.Setup(m => m.Attributes).Returns(new List <AttrAttribute> { descAttr }); targetedFields.Setup(m => m.Relationships).Returns(new List <RelationshipAttribute>()); // Act await repository.UpdateAsync(todoItemUpdates, databaseEntity); } // Assert - in different context await using var assertContext = GetContext(seed); { var(repository, _) = Setup(assertContext); var fetchedTodo = repository.Get(itemId).First(); Assert.NotNull(fetchedTodo); Assert.Equal(databaseEntity.Ordinal, fetchedTodo.Ordinal); Assert.Equal(todoItemUpdates.Description, fetchedTodo.Description); } }